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        if self.buf.len() == self.pos {
284            return None;
285        }
286        let pos = self.pos;
287        let mut r#type = None;
288        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
289            r#type = Some(header.r#type);
290            let res = match header.r#type {
291                1u16 => Dev::Ifindex({
292                    let res = parse_u32(next);
293                    let Some(val) = res else { break };
294                    val
295                }),
296                2u16 => Dev::Pad({
297                    let res = Some(next);
298                    let Some(val) = res else { break };
299                    val
300                }),
301                3u16 => Dev::XdpFeatures({
302                    let res = parse_u64(next);
303                    let Some(val) = res else { break };
304                    val
305                }),
306                4u16 => Dev::XdpZcMaxSegs({
307                    let res = parse_u32(next);
308                    let Some(val) = res else { break };
309                    val
310                }),
311                5u16 => Dev::XdpRxMetadataFeatures({
312                    let res = parse_u64(next);
313                    let Some(val) = res else { break };
314                    val
315                }),
316                6u16 => Dev::XskFeatures({
317                    let res = parse_u64(next);
318                    let Some(val) = res else { break };
319                    val
320                }),
321                n => {
322                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
323                        break;
324                    } else {
325                        continue;
326                    }
327                }
328            };
329            return Some(Ok(res));
330        }
331        Some(Err(ErrorContext::new(
332            "Dev",
333            r#type.and_then(|t| Dev::attr_from_type(t)),
334            self.orig_loc,
335            self.buf.as_ptr().wrapping_add(pos) as usize,
336        )))
337    }
338}
339impl<'a> std::fmt::Debug for IterableDev<'_> {
340    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
341        let mut fmt = f.debug_struct("Dev");
342        for attr in self.clone() {
343            let attr = match attr {
344                Ok(a) => a,
345                Err(err) => {
346                    fmt.finish()?;
347                    f.write_str("Err(")?;
348                    err.fmt(f)?;
349                    return f.write_str(")");
350                }
351            };
352            match attr {
353                Dev::Ifindex(val) => fmt.field("Ifindex", &val),
354                Dev::Pad(val) => fmt.field("Pad", &val),
355                Dev::XdpFeatures(val) => {
356                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
357                }
358                Dev::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
359                Dev::XdpRxMetadataFeatures(val) => fmt.field(
360                    "XdpRxMetadataFeatures",
361                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
362                ),
363                Dev::XskFeatures(val) => fmt.field(
364                    "XskFeatures",
365                    &FormatFlags(val.into(), XskFlags::from_value),
366                ),
367            };
368        }
369        fmt.finish()
370    }
371}
372impl IterableDev<'_> {
373    pub fn lookup_attr(
374        &self,
375        offset: usize,
376        missing_type: Option<u16>,
377    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
378        let mut stack = Vec::new();
379        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
380        if cur == offset {
381            stack.push(("Dev", offset));
382            return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
383        }
384        if cur > offset || cur + self.buf.len() < offset {
385            return (stack, None);
386        }
387        let mut attrs = self.clone();
388        let mut last_off = cur + attrs.pos;
389        while let Some(attr) = attrs.next() {
390            let Ok(attr) = attr else { break };
391            match attr {
392                Dev::Ifindex(val) => {
393                    if last_off == offset {
394                        stack.push(("Ifindex", last_off));
395                        break;
396                    }
397                }
398                Dev::Pad(val) => {
399                    if last_off == offset {
400                        stack.push(("Pad", last_off));
401                        break;
402                    }
403                }
404                Dev::XdpFeatures(val) => {
405                    if last_off == offset {
406                        stack.push(("XdpFeatures", last_off));
407                        break;
408                    }
409                }
410                Dev::XdpZcMaxSegs(val) => {
411                    if last_off == offset {
412                        stack.push(("XdpZcMaxSegs", last_off));
413                        break;
414                    }
415                }
416                Dev::XdpRxMetadataFeatures(val) => {
417                    if last_off == offset {
418                        stack.push(("XdpRxMetadataFeatures", last_off));
419                        break;
420                    }
421                }
422                Dev::XskFeatures(val) => {
423                    if last_off == offset {
424                        stack.push(("XskFeatures", last_off));
425                        break;
426                    }
427                }
428                _ => {}
429            };
430            last_off = cur + attrs.pos;
431        }
432        if !stack.is_empty() {
433            stack.push(("Dev", cur));
434        }
435        (stack, None)
436    }
437}
438#[derive(Clone)]
439pub enum IoUringProviderInfo {}
440impl<'a> IterableIoUringProviderInfo<'a> {}
441impl IoUringProviderInfo {
442    pub fn new<'a>(buf: &'a [u8]) -> IterableIoUringProviderInfo<'a> {
443        IterableIoUringProviderInfo::with_loc(buf, buf.as_ptr() as usize)
444    }
445    fn attr_from_type(r#type: u16) -> Option<&'static str> {
446        None
447    }
448}
449#[derive(Clone, Copy, Default)]
450pub struct IterableIoUringProviderInfo<'a> {
451    buf: &'a [u8],
452    pos: usize,
453    orig_loc: usize,
454}
455impl<'a> IterableIoUringProviderInfo<'a> {
456    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
457        Self {
458            buf,
459            pos: 0,
460            orig_loc,
461        }
462    }
463    pub fn get_buf(&self) -> &'a [u8] {
464        self.buf
465    }
466}
467impl<'a> Iterator for IterableIoUringProviderInfo<'a> {
468    type Item = Result<IoUringProviderInfo, ErrorContext>;
469    fn next(&mut self) -> Option<Self::Item> {
470        if self.buf.len() == self.pos {
471            return None;
472        }
473        let pos = self.pos;
474        let mut r#type = None;
475        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
476            r#type = Some(header.r#type);
477            let res = match header.r#type {
478                n => {
479                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
480                        break;
481                    } else {
482                        continue;
483                    }
484                }
485            };
486            return Some(Ok(res));
487        }
488        Some(Err(ErrorContext::new(
489            "IoUringProviderInfo",
490            r#type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
491            self.orig_loc,
492            self.buf.as_ptr().wrapping_add(pos) as usize,
493        )))
494    }
495}
496impl std::fmt::Debug for IterableIoUringProviderInfo<'_> {
497    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
498        let mut fmt = f.debug_struct("IoUringProviderInfo");
499        for attr in self.clone() {
500            let attr = match attr {
501                Ok(a) => a,
502                Err(err) => {
503                    fmt.finish()?;
504                    f.write_str("Err(")?;
505                    err.fmt(f)?;
506                    return f.write_str(")");
507                }
508            };
509            match attr {};
510        }
511        fmt.finish()
512    }
513}
514impl IterableIoUringProviderInfo<'_> {
515    pub fn lookup_attr(
516        &self,
517        offset: usize,
518        missing_type: Option<u16>,
519    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
520        let mut stack = Vec::new();
521        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
522        if cur == offset {
523            stack.push(("IoUringProviderInfo", offset));
524            return (
525                stack,
526                missing_type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
527            );
528        }
529        (stack, None)
530    }
531}
532#[derive(Clone)]
533pub enum PagePool<'a> {
534    #[doc = "Unique ID of a Page Pool instance."]
535    Id(u32),
536    #[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"]
537    Ifindex(u32),
538    #[doc = "Id of NAPI using this Page Pool instance."]
539    NapiId(u32),
540    #[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"]
541    Inflight(u32),
542    #[doc = "Amount of memory held by inflight pages.\n"]
543    InflightMem(u32),
544    #[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"]
545    DetachTime(u32),
546    #[doc = "ID of the dmabuf this page-pool is attached to."]
547    Dmabuf(u32),
548    #[doc = "io-uring memory provider information."]
549    IoUring(IterableIoUringProviderInfo<'a>),
550}
551impl<'a> IterablePagePool<'a> {
552    #[doc = "Unique ID of a Page Pool instance."]
553    pub fn get_id(&self) -> Result<u32, ErrorContext> {
554        let mut iter = self.clone();
555        iter.pos = 0;
556        for attr in iter {
557            if let PagePool::Id(val) = attr? {
558                return Ok(val);
559            }
560        }
561        Err(ErrorContext::new_missing(
562            "PagePool",
563            "Id",
564            self.orig_loc,
565            self.buf.as_ptr() as usize,
566        ))
567    }
568    #[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"]
569    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
570        let mut iter = self.clone();
571        iter.pos = 0;
572        for attr in iter {
573            if let PagePool::Ifindex(val) = attr? {
574                return Ok(val);
575            }
576        }
577        Err(ErrorContext::new_missing(
578            "PagePool",
579            "Ifindex",
580            self.orig_loc,
581            self.buf.as_ptr() as usize,
582        ))
583    }
584    #[doc = "Id of NAPI using this Page Pool instance."]
585    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
586        let mut iter = self.clone();
587        iter.pos = 0;
588        for attr in iter {
589            if let PagePool::NapiId(val) = attr? {
590                return Ok(val);
591            }
592        }
593        Err(ErrorContext::new_missing(
594            "PagePool",
595            "NapiId",
596            self.orig_loc,
597            self.buf.as_ptr() as usize,
598        ))
599    }
600    #[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"]
601    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
602        let mut iter = self.clone();
603        iter.pos = 0;
604        for attr in iter {
605            if let PagePool::Inflight(val) = attr? {
606                return Ok(val);
607            }
608        }
609        Err(ErrorContext::new_missing(
610            "PagePool",
611            "Inflight",
612            self.orig_loc,
613            self.buf.as_ptr() as usize,
614        ))
615    }
616    #[doc = "Amount of memory held by inflight pages.\n"]
617    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
618        let mut iter = self.clone();
619        iter.pos = 0;
620        for attr in iter {
621            if let PagePool::InflightMem(val) = attr? {
622                return Ok(val);
623            }
624        }
625        Err(ErrorContext::new_missing(
626            "PagePool",
627            "InflightMem",
628            self.orig_loc,
629            self.buf.as_ptr() as usize,
630        ))
631    }
632    #[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"]
633    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
634        let mut iter = self.clone();
635        iter.pos = 0;
636        for attr in iter {
637            if let PagePool::DetachTime(val) = attr? {
638                return Ok(val);
639            }
640        }
641        Err(ErrorContext::new_missing(
642            "PagePool",
643            "DetachTime",
644            self.orig_loc,
645            self.buf.as_ptr() as usize,
646        ))
647    }
648    #[doc = "ID of the dmabuf this page-pool is attached to."]
649    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
650        let mut iter = self.clone();
651        iter.pos = 0;
652        for attr in iter {
653            if let PagePool::Dmabuf(val) = attr? {
654                return Ok(val);
655            }
656        }
657        Err(ErrorContext::new_missing(
658            "PagePool",
659            "Dmabuf",
660            self.orig_loc,
661            self.buf.as_ptr() as usize,
662        ))
663    }
664    #[doc = "io-uring memory provider information."]
665    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
666        let mut iter = self.clone();
667        iter.pos = 0;
668        for attr in iter {
669            if let PagePool::IoUring(val) = attr? {
670                return Ok(val);
671            }
672        }
673        Err(ErrorContext::new_missing(
674            "PagePool",
675            "IoUring",
676            self.orig_loc,
677            self.buf.as_ptr() as usize,
678        ))
679    }
680}
681impl PagePool<'_> {
682    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
683        IterablePagePool::with_loc(buf, buf.as_ptr() as usize)
684    }
685    fn attr_from_type(r#type: u16) -> Option<&'static str> {
686        let res = match r#type {
687            1u16 => "Id",
688            2u16 => "Ifindex",
689            3u16 => "NapiId",
690            4u16 => "Inflight",
691            5u16 => "InflightMem",
692            6u16 => "DetachTime",
693            7u16 => "Dmabuf",
694            8u16 => "IoUring",
695            _ => return None,
696        };
697        Some(res)
698    }
699}
700#[derive(Clone, Copy, Default)]
701pub struct IterablePagePool<'a> {
702    buf: &'a [u8],
703    pos: usize,
704    orig_loc: usize,
705}
706impl<'a> IterablePagePool<'a> {
707    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
708        Self {
709            buf,
710            pos: 0,
711            orig_loc,
712        }
713    }
714    pub fn get_buf(&self) -> &'a [u8] {
715        self.buf
716    }
717}
718impl<'a> Iterator for IterablePagePool<'a> {
719    type Item = Result<PagePool<'a>, ErrorContext>;
720    fn next(&mut self) -> Option<Self::Item> {
721        if self.buf.len() == self.pos {
722            return None;
723        }
724        let pos = self.pos;
725        let mut r#type = None;
726        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
727            r#type = Some(header.r#type);
728            let res = match header.r#type {
729                1u16 => PagePool::Id({
730                    let res = parse_u32(next);
731                    let Some(val) = res else { break };
732                    val
733                }),
734                2u16 => PagePool::Ifindex({
735                    let res = parse_u32(next);
736                    let Some(val) = res else { break };
737                    val
738                }),
739                3u16 => PagePool::NapiId({
740                    let res = parse_u32(next);
741                    let Some(val) = res else { break };
742                    val
743                }),
744                4u16 => PagePool::Inflight({
745                    let res = parse_u32(next);
746                    let Some(val) = res else { break };
747                    val
748                }),
749                5u16 => PagePool::InflightMem({
750                    let res = parse_u32(next);
751                    let Some(val) = res else { break };
752                    val
753                }),
754                6u16 => PagePool::DetachTime({
755                    let res = parse_u32(next);
756                    let Some(val) = res else { break };
757                    val
758                }),
759                7u16 => PagePool::Dmabuf({
760                    let res = parse_u32(next);
761                    let Some(val) = res else { break };
762                    val
763                }),
764                8u16 => PagePool::IoUring({
765                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
766                    let Some(val) = res else { break };
767                    val
768                }),
769                n => {
770                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
771                        break;
772                    } else {
773                        continue;
774                    }
775                }
776            };
777            return Some(Ok(res));
778        }
779        Some(Err(ErrorContext::new(
780            "PagePool",
781            r#type.and_then(|t| PagePool::attr_from_type(t)),
782            self.orig_loc,
783            self.buf.as_ptr().wrapping_add(pos) as usize,
784        )))
785    }
786}
787impl<'a> std::fmt::Debug for IterablePagePool<'_> {
788    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
789        let mut fmt = f.debug_struct("PagePool");
790        for attr in self.clone() {
791            let attr = match attr {
792                Ok(a) => a,
793                Err(err) => {
794                    fmt.finish()?;
795                    f.write_str("Err(")?;
796                    err.fmt(f)?;
797                    return f.write_str(")");
798                }
799            };
800            match attr {
801                PagePool::Id(val) => fmt.field("Id", &val),
802                PagePool::Ifindex(val) => fmt.field("Ifindex", &val),
803                PagePool::NapiId(val) => fmt.field("NapiId", &val),
804                PagePool::Inflight(val) => fmt.field("Inflight", &val),
805                PagePool::InflightMem(val) => fmt.field("InflightMem", &val),
806                PagePool::DetachTime(val) => fmt.field("DetachTime", &val),
807                PagePool::Dmabuf(val) => fmt.field("Dmabuf", &val),
808                PagePool::IoUring(val) => fmt.field("IoUring", &val),
809            };
810        }
811        fmt.finish()
812    }
813}
814impl IterablePagePool<'_> {
815    pub fn lookup_attr(
816        &self,
817        offset: usize,
818        missing_type: Option<u16>,
819    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
820        let mut stack = Vec::new();
821        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
822        if cur == offset {
823            stack.push(("PagePool", offset));
824            return (
825                stack,
826                missing_type.and_then(|t| PagePool::attr_from_type(t)),
827            );
828        }
829        if cur > offset || cur + self.buf.len() < offset {
830            return (stack, None);
831        }
832        let mut attrs = self.clone();
833        let mut last_off = cur + attrs.pos;
834        let mut missing = None;
835        while let Some(attr) = attrs.next() {
836            let Ok(attr) = attr else { break };
837            match attr {
838                PagePool::Id(val) => {
839                    if last_off == offset {
840                        stack.push(("Id", last_off));
841                        break;
842                    }
843                }
844                PagePool::Ifindex(val) => {
845                    if last_off == offset {
846                        stack.push(("Ifindex", last_off));
847                        break;
848                    }
849                }
850                PagePool::NapiId(val) => {
851                    if last_off == offset {
852                        stack.push(("NapiId", last_off));
853                        break;
854                    }
855                }
856                PagePool::Inflight(val) => {
857                    if last_off == offset {
858                        stack.push(("Inflight", last_off));
859                        break;
860                    }
861                }
862                PagePool::InflightMem(val) => {
863                    if last_off == offset {
864                        stack.push(("InflightMem", last_off));
865                        break;
866                    }
867                }
868                PagePool::DetachTime(val) => {
869                    if last_off == offset {
870                        stack.push(("DetachTime", last_off));
871                        break;
872                    }
873                }
874                PagePool::Dmabuf(val) => {
875                    if last_off == offset {
876                        stack.push(("Dmabuf", last_off));
877                        break;
878                    }
879                }
880                PagePool::IoUring(val) => {
881                    (stack, missing) = val.lookup_attr(offset, missing_type);
882                    if !stack.is_empty() {
883                        break;
884                    }
885                }
886                _ => {}
887            };
888            last_off = cur + attrs.pos;
889        }
890        if !stack.is_empty() {
891            stack.push(("PagePool", cur));
892        }
893        (stack, missing)
894    }
895}
896#[derive(Clone)]
897pub enum PagePoolInfo {
898    #[doc = "Unique ID of a Page Pool instance."]
899    Id(u32),
900    #[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"]
901    Ifindex(u32),
902}
903impl<'a> IterablePagePoolInfo<'a> {
904    #[doc = "Unique ID of a Page Pool instance."]
905    pub fn get_id(&self) -> Result<u32, ErrorContext> {
906        let mut iter = self.clone();
907        iter.pos = 0;
908        for attr in iter {
909            if let PagePoolInfo::Id(val) = attr? {
910                return Ok(val);
911            }
912        }
913        Err(ErrorContext::new_missing(
914            "PagePoolInfo",
915            "Id",
916            self.orig_loc,
917            self.buf.as_ptr() as usize,
918        ))
919    }
920    #[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"]
921    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
922        let mut iter = self.clone();
923        iter.pos = 0;
924        for attr in iter {
925            if let PagePoolInfo::Ifindex(val) = attr? {
926                return Ok(val);
927            }
928        }
929        Err(ErrorContext::new_missing(
930            "PagePoolInfo",
931            "Ifindex",
932            self.orig_loc,
933            self.buf.as_ptr() as usize,
934        ))
935    }
936}
937impl PagePoolInfo {
938    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolInfo<'a> {
939        IterablePagePoolInfo::with_loc(buf, buf.as_ptr() as usize)
940    }
941    fn attr_from_type(r#type: u16) -> Option<&'static str> {
942        PagePool::attr_from_type(r#type)
943    }
944}
945#[derive(Clone, Copy, Default)]
946pub struct IterablePagePoolInfo<'a> {
947    buf: &'a [u8],
948    pos: usize,
949    orig_loc: usize,
950}
951impl<'a> IterablePagePoolInfo<'a> {
952    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
953        Self {
954            buf,
955            pos: 0,
956            orig_loc,
957        }
958    }
959    pub fn get_buf(&self) -> &'a [u8] {
960        self.buf
961    }
962}
963impl<'a> Iterator for IterablePagePoolInfo<'a> {
964    type Item = Result<PagePoolInfo, ErrorContext>;
965    fn next(&mut self) -> Option<Self::Item> {
966        if self.buf.len() == self.pos {
967            return None;
968        }
969        let pos = self.pos;
970        let mut r#type = None;
971        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
972            r#type = Some(header.r#type);
973            let res = match header.r#type {
974                1u16 => PagePoolInfo::Id({
975                    let res = parse_u32(next);
976                    let Some(val) = res else { break };
977                    val
978                }),
979                2u16 => PagePoolInfo::Ifindex({
980                    let res = parse_u32(next);
981                    let Some(val) = res else { break };
982                    val
983                }),
984                n => {
985                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
986                        break;
987                    } else {
988                        continue;
989                    }
990                }
991            };
992            return Some(Ok(res));
993        }
994        Some(Err(ErrorContext::new(
995            "PagePoolInfo",
996            r#type.and_then(|t| PagePoolInfo::attr_from_type(t)),
997            self.orig_loc,
998            self.buf.as_ptr().wrapping_add(pos) as usize,
999        )))
1000    }
1001}
1002impl std::fmt::Debug for IterablePagePoolInfo<'_> {
1003    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1004        let mut fmt = f.debug_struct("PagePoolInfo");
1005        for attr in self.clone() {
1006            let attr = match attr {
1007                Ok(a) => a,
1008                Err(err) => {
1009                    fmt.finish()?;
1010                    f.write_str("Err(")?;
1011                    err.fmt(f)?;
1012                    return f.write_str(")");
1013                }
1014            };
1015            match attr {
1016                PagePoolInfo::Id(val) => fmt.field("Id", &val),
1017                PagePoolInfo::Ifindex(val) => fmt.field("Ifindex", &val),
1018            };
1019        }
1020        fmt.finish()
1021    }
1022}
1023impl IterablePagePoolInfo<'_> {
1024    pub fn lookup_attr(
1025        &self,
1026        offset: usize,
1027        missing_type: Option<u16>,
1028    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1029        let mut stack = Vec::new();
1030        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1031        if cur == offset {
1032            stack.push(("PagePoolInfo", offset));
1033            return (
1034                stack,
1035                missing_type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1036            );
1037        }
1038        if cur > offset || cur + self.buf.len() < offset {
1039            return (stack, None);
1040        }
1041        let mut attrs = self.clone();
1042        let mut last_off = cur + attrs.pos;
1043        while let Some(attr) = attrs.next() {
1044            let Ok(attr) = attr else { break };
1045            match attr {
1046                PagePoolInfo::Id(val) => {
1047                    if last_off == offset {
1048                        stack.push(("Id", last_off));
1049                        break;
1050                    }
1051                }
1052                PagePoolInfo::Ifindex(val) => {
1053                    if last_off == offset {
1054                        stack.push(("Ifindex", last_off));
1055                        break;
1056                    }
1057                }
1058                _ => {}
1059            };
1060            last_off = cur + attrs.pos;
1061        }
1062        if !stack.is_empty() {
1063            stack.push(("PagePoolInfo", cur));
1064        }
1065        (stack, None)
1066    }
1067}
1068#[derive(Clone)]
1069pub enum PagePoolStats<'a> {
1070    #[doc = "Page pool identifying information."]
1071    Info(IterablePagePoolInfo<'a>),
1072    AllocFast(u32),
1073    AllocSlow(u32),
1074    AllocSlowHighOrder(u32),
1075    AllocEmpty(u32),
1076    AllocRefill(u32),
1077    AllocWaive(u32),
1078    RecycleCached(u32),
1079    RecycleCacheFull(u32),
1080    RecycleRing(u32),
1081    RecycleRingFull(u32),
1082    RecycleReleasedRefcnt(u32),
1083}
1084impl<'a> IterablePagePoolStats<'a> {
1085    #[doc = "Page pool identifying information."]
1086    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
1087        let mut iter = self.clone();
1088        iter.pos = 0;
1089        for attr in iter {
1090            if let PagePoolStats::Info(val) = attr? {
1091                return Ok(val);
1092            }
1093        }
1094        Err(ErrorContext::new_missing(
1095            "PagePoolStats",
1096            "Info",
1097            self.orig_loc,
1098            self.buf.as_ptr() as usize,
1099        ))
1100    }
1101    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
1102        let mut iter = self.clone();
1103        iter.pos = 0;
1104        for attr in iter {
1105            if let PagePoolStats::AllocFast(val) = attr? {
1106                return Ok(val);
1107            }
1108        }
1109        Err(ErrorContext::new_missing(
1110            "PagePoolStats",
1111            "AllocFast",
1112            self.orig_loc,
1113            self.buf.as_ptr() as usize,
1114        ))
1115    }
1116    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
1117        let mut iter = self.clone();
1118        iter.pos = 0;
1119        for attr in iter {
1120            if let PagePoolStats::AllocSlow(val) = attr? {
1121                return Ok(val);
1122            }
1123        }
1124        Err(ErrorContext::new_missing(
1125            "PagePoolStats",
1126            "AllocSlow",
1127            self.orig_loc,
1128            self.buf.as_ptr() as usize,
1129        ))
1130    }
1131    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
1132        let mut iter = self.clone();
1133        iter.pos = 0;
1134        for attr in iter {
1135            if let PagePoolStats::AllocSlowHighOrder(val) = attr? {
1136                return Ok(val);
1137            }
1138        }
1139        Err(ErrorContext::new_missing(
1140            "PagePoolStats",
1141            "AllocSlowHighOrder",
1142            self.orig_loc,
1143            self.buf.as_ptr() as usize,
1144        ))
1145    }
1146    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
1147        let mut iter = self.clone();
1148        iter.pos = 0;
1149        for attr in iter {
1150            if let PagePoolStats::AllocEmpty(val) = attr? {
1151                return Ok(val);
1152            }
1153        }
1154        Err(ErrorContext::new_missing(
1155            "PagePoolStats",
1156            "AllocEmpty",
1157            self.orig_loc,
1158            self.buf.as_ptr() as usize,
1159        ))
1160    }
1161    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
1162        let mut iter = self.clone();
1163        iter.pos = 0;
1164        for attr in iter {
1165            if let PagePoolStats::AllocRefill(val) = attr? {
1166                return Ok(val);
1167            }
1168        }
1169        Err(ErrorContext::new_missing(
1170            "PagePoolStats",
1171            "AllocRefill",
1172            self.orig_loc,
1173            self.buf.as_ptr() as usize,
1174        ))
1175    }
1176    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
1177        let mut iter = self.clone();
1178        iter.pos = 0;
1179        for attr in iter {
1180            if let PagePoolStats::AllocWaive(val) = attr? {
1181                return Ok(val);
1182            }
1183        }
1184        Err(ErrorContext::new_missing(
1185            "PagePoolStats",
1186            "AllocWaive",
1187            self.orig_loc,
1188            self.buf.as_ptr() as usize,
1189        ))
1190    }
1191    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
1192        let mut iter = self.clone();
1193        iter.pos = 0;
1194        for attr in iter {
1195            if let PagePoolStats::RecycleCached(val) = attr? {
1196                return Ok(val);
1197            }
1198        }
1199        Err(ErrorContext::new_missing(
1200            "PagePoolStats",
1201            "RecycleCached",
1202            self.orig_loc,
1203            self.buf.as_ptr() as usize,
1204        ))
1205    }
1206    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
1207        let mut iter = self.clone();
1208        iter.pos = 0;
1209        for attr in iter {
1210            if let PagePoolStats::RecycleCacheFull(val) = attr? {
1211                return Ok(val);
1212            }
1213        }
1214        Err(ErrorContext::new_missing(
1215            "PagePoolStats",
1216            "RecycleCacheFull",
1217            self.orig_loc,
1218            self.buf.as_ptr() as usize,
1219        ))
1220    }
1221    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
1222        let mut iter = self.clone();
1223        iter.pos = 0;
1224        for attr in iter {
1225            if let PagePoolStats::RecycleRing(val) = attr? {
1226                return Ok(val);
1227            }
1228        }
1229        Err(ErrorContext::new_missing(
1230            "PagePoolStats",
1231            "RecycleRing",
1232            self.orig_loc,
1233            self.buf.as_ptr() as usize,
1234        ))
1235    }
1236    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
1237        let mut iter = self.clone();
1238        iter.pos = 0;
1239        for attr in iter {
1240            if let PagePoolStats::RecycleRingFull(val) = attr? {
1241                return Ok(val);
1242            }
1243        }
1244        Err(ErrorContext::new_missing(
1245            "PagePoolStats",
1246            "RecycleRingFull",
1247            self.orig_loc,
1248            self.buf.as_ptr() as usize,
1249        ))
1250    }
1251    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
1252        let mut iter = self.clone();
1253        iter.pos = 0;
1254        for attr in iter {
1255            if let PagePoolStats::RecycleReleasedRefcnt(val) = attr? {
1256                return Ok(val);
1257            }
1258        }
1259        Err(ErrorContext::new_missing(
1260            "PagePoolStats",
1261            "RecycleReleasedRefcnt",
1262            self.orig_loc,
1263            self.buf.as_ptr() as usize,
1264        ))
1265    }
1266}
1267impl PagePoolStats<'_> {
1268    pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
1269        IterablePagePoolStats::with_loc(buf, buf.as_ptr() as usize)
1270    }
1271    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1272        let res = match r#type {
1273            1u16 => "Info",
1274            8u16 => "AllocFast",
1275            9u16 => "AllocSlow",
1276            10u16 => "AllocSlowHighOrder",
1277            11u16 => "AllocEmpty",
1278            12u16 => "AllocRefill",
1279            13u16 => "AllocWaive",
1280            14u16 => "RecycleCached",
1281            15u16 => "RecycleCacheFull",
1282            16u16 => "RecycleRing",
1283            17u16 => "RecycleRingFull",
1284            18u16 => "RecycleReleasedRefcnt",
1285            _ => return None,
1286        };
1287        Some(res)
1288    }
1289}
1290#[derive(Clone, Copy, Default)]
1291pub struct IterablePagePoolStats<'a> {
1292    buf: &'a [u8],
1293    pos: usize,
1294    orig_loc: usize,
1295}
1296impl<'a> IterablePagePoolStats<'a> {
1297    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1298        Self {
1299            buf,
1300            pos: 0,
1301            orig_loc,
1302        }
1303    }
1304    pub fn get_buf(&self) -> &'a [u8] {
1305        self.buf
1306    }
1307}
1308impl<'a> Iterator for IterablePagePoolStats<'a> {
1309    type Item = Result<PagePoolStats<'a>, ErrorContext>;
1310    fn next(&mut self) -> Option<Self::Item> {
1311        if self.buf.len() == self.pos {
1312            return None;
1313        }
1314        let pos = self.pos;
1315        let mut r#type = None;
1316        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
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 => {
1380                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
1381                        break;
1382                    } else {
1383                        continue;
1384                    }
1385                }
1386            };
1387            return Some(Ok(res));
1388        }
1389        Some(Err(ErrorContext::new(
1390            "PagePoolStats",
1391            r#type.and_then(|t| PagePoolStats::attr_from_type(t)),
1392            self.orig_loc,
1393            self.buf.as_ptr().wrapping_add(pos) as usize,
1394        )))
1395    }
1396}
1397impl<'a> std::fmt::Debug for IterablePagePoolStats<'_> {
1398    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1399        let mut fmt = f.debug_struct("PagePoolStats");
1400        for attr in self.clone() {
1401            let attr = match attr {
1402                Ok(a) => a,
1403                Err(err) => {
1404                    fmt.finish()?;
1405                    f.write_str("Err(")?;
1406                    err.fmt(f)?;
1407                    return f.write_str(")");
1408                }
1409            };
1410            match attr {
1411                PagePoolStats::Info(val) => fmt.field("Info", &val),
1412                PagePoolStats::AllocFast(val) => fmt.field("AllocFast", &val),
1413                PagePoolStats::AllocSlow(val) => fmt.field("AllocSlow", &val),
1414                PagePoolStats::AllocSlowHighOrder(val) => fmt.field("AllocSlowHighOrder", &val),
1415                PagePoolStats::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
1416                PagePoolStats::AllocRefill(val) => fmt.field("AllocRefill", &val),
1417                PagePoolStats::AllocWaive(val) => fmt.field("AllocWaive", &val),
1418                PagePoolStats::RecycleCached(val) => fmt.field("RecycleCached", &val),
1419                PagePoolStats::RecycleCacheFull(val) => fmt.field("RecycleCacheFull", &val),
1420                PagePoolStats::RecycleRing(val) => fmt.field("RecycleRing", &val),
1421                PagePoolStats::RecycleRingFull(val) => fmt.field("RecycleRingFull", &val),
1422                PagePoolStats::RecycleReleasedRefcnt(val) => {
1423                    fmt.field("RecycleReleasedRefcnt", &val)
1424                }
1425            };
1426        }
1427        fmt.finish()
1428    }
1429}
1430impl IterablePagePoolStats<'_> {
1431    pub fn lookup_attr(
1432        &self,
1433        offset: usize,
1434        missing_type: Option<u16>,
1435    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1436        let mut stack = Vec::new();
1437        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1438        if cur == offset {
1439            stack.push(("PagePoolStats", offset));
1440            return (
1441                stack,
1442                missing_type.and_then(|t| PagePoolStats::attr_from_type(t)),
1443            );
1444        }
1445        if cur > offset || cur + self.buf.len() < offset {
1446            return (stack, None);
1447        }
1448        let mut attrs = self.clone();
1449        let mut last_off = cur + attrs.pos;
1450        let mut missing = None;
1451        while let Some(attr) = attrs.next() {
1452            let Ok(attr) = attr else { break };
1453            match attr {
1454                PagePoolStats::Info(val) => {
1455                    (stack, missing) = val.lookup_attr(offset, missing_type);
1456                    if !stack.is_empty() {
1457                        break;
1458                    }
1459                }
1460                PagePoolStats::AllocFast(val) => {
1461                    if last_off == offset {
1462                        stack.push(("AllocFast", last_off));
1463                        break;
1464                    }
1465                }
1466                PagePoolStats::AllocSlow(val) => {
1467                    if last_off == offset {
1468                        stack.push(("AllocSlow", last_off));
1469                        break;
1470                    }
1471                }
1472                PagePoolStats::AllocSlowHighOrder(val) => {
1473                    if last_off == offset {
1474                        stack.push(("AllocSlowHighOrder", last_off));
1475                        break;
1476                    }
1477                }
1478                PagePoolStats::AllocEmpty(val) => {
1479                    if last_off == offset {
1480                        stack.push(("AllocEmpty", last_off));
1481                        break;
1482                    }
1483                }
1484                PagePoolStats::AllocRefill(val) => {
1485                    if last_off == offset {
1486                        stack.push(("AllocRefill", last_off));
1487                        break;
1488                    }
1489                }
1490                PagePoolStats::AllocWaive(val) => {
1491                    if last_off == offset {
1492                        stack.push(("AllocWaive", last_off));
1493                        break;
1494                    }
1495                }
1496                PagePoolStats::RecycleCached(val) => {
1497                    if last_off == offset {
1498                        stack.push(("RecycleCached", last_off));
1499                        break;
1500                    }
1501                }
1502                PagePoolStats::RecycleCacheFull(val) => {
1503                    if last_off == offset {
1504                        stack.push(("RecycleCacheFull", last_off));
1505                        break;
1506                    }
1507                }
1508                PagePoolStats::RecycleRing(val) => {
1509                    if last_off == offset {
1510                        stack.push(("RecycleRing", last_off));
1511                        break;
1512                    }
1513                }
1514                PagePoolStats::RecycleRingFull(val) => {
1515                    if last_off == offset {
1516                        stack.push(("RecycleRingFull", last_off));
1517                        break;
1518                    }
1519                }
1520                PagePoolStats::RecycleReleasedRefcnt(val) => {
1521                    if last_off == offset {
1522                        stack.push(("RecycleReleasedRefcnt", last_off));
1523                        break;
1524                    }
1525                }
1526                _ => {}
1527            };
1528            last_off = cur + attrs.pos;
1529        }
1530        if !stack.is_empty() {
1531            stack.push(("PagePoolStats", cur));
1532        }
1533        (stack, missing)
1534    }
1535}
1536#[derive(Clone)]
1537pub enum Napi {
1538    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1539    Ifindex(u32),
1540    #[doc = "ID of the NAPI instance."]
1541    Id(u32),
1542    #[doc = "The associated interrupt vector number for the napi"]
1543    Irq(u32),
1544    #[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."]
1545    Pid(u32),
1546    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1547    DeferHardIrqs(u32),
1548    #[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."]
1549    GroFlushTimeout(u32),
1550    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1551    IrqSuspendTimeout(u32),
1552    #[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)"]
1553    Threaded(u32),
1554}
1555impl<'a> IterableNapi<'a> {
1556    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1557    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1558        let mut iter = self.clone();
1559        iter.pos = 0;
1560        for attr in iter {
1561            if let Napi::Ifindex(val) = attr? {
1562                return Ok(val);
1563            }
1564        }
1565        Err(ErrorContext::new_missing(
1566            "Napi",
1567            "Ifindex",
1568            self.orig_loc,
1569            self.buf.as_ptr() as usize,
1570        ))
1571    }
1572    #[doc = "ID of the NAPI instance."]
1573    pub fn get_id(&self) -> Result<u32, ErrorContext> {
1574        let mut iter = self.clone();
1575        iter.pos = 0;
1576        for attr in iter {
1577            if let Napi::Id(val) = attr? {
1578                return Ok(val);
1579            }
1580        }
1581        Err(ErrorContext::new_missing(
1582            "Napi",
1583            "Id",
1584            self.orig_loc,
1585            self.buf.as_ptr() as usize,
1586        ))
1587    }
1588    #[doc = "The associated interrupt vector number for the napi"]
1589    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
1590        let mut iter = self.clone();
1591        iter.pos = 0;
1592        for attr in iter {
1593            if let Napi::Irq(val) = attr? {
1594                return Ok(val);
1595            }
1596        }
1597        Err(ErrorContext::new_missing(
1598            "Napi",
1599            "Irq",
1600            self.orig_loc,
1601            self.buf.as_ptr() as usize,
1602        ))
1603    }
1604    #[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."]
1605    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
1606        let mut iter = self.clone();
1607        iter.pos = 0;
1608        for attr in iter {
1609            if let Napi::Pid(val) = attr? {
1610                return Ok(val);
1611            }
1612        }
1613        Err(ErrorContext::new_missing(
1614            "Napi",
1615            "Pid",
1616            self.orig_loc,
1617            self.buf.as_ptr() as usize,
1618        ))
1619    }
1620    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1621    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
1622        let mut iter = self.clone();
1623        iter.pos = 0;
1624        for attr in iter {
1625            if let Napi::DeferHardIrqs(val) = attr? {
1626                return Ok(val);
1627            }
1628        }
1629        Err(ErrorContext::new_missing(
1630            "Napi",
1631            "DeferHardIrqs",
1632            self.orig_loc,
1633            self.buf.as_ptr() as usize,
1634        ))
1635    }
1636    #[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."]
1637    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
1638        let mut iter = self.clone();
1639        iter.pos = 0;
1640        for attr in iter {
1641            if let Napi::GroFlushTimeout(val) = attr? {
1642                return Ok(val);
1643            }
1644        }
1645        Err(ErrorContext::new_missing(
1646            "Napi",
1647            "GroFlushTimeout",
1648            self.orig_loc,
1649            self.buf.as_ptr() as usize,
1650        ))
1651    }
1652    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1653    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
1654        let mut iter = self.clone();
1655        iter.pos = 0;
1656        for attr in iter {
1657            if let Napi::IrqSuspendTimeout(val) = attr? {
1658                return Ok(val);
1659            }
1660        }
1661        Err(ErrorContext::new_missing(
1662            "Napi",
1663            "IrqSuspendTimeout",
1664            self.orig_loc,
1665            self.buf.as_ptr() as usize,
1666        ))
1667    }
1668    #[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)"]
1669    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
1670        let mut iter = self.clone();
1671        iter.pos = 0;
1672        for attr in iter {
1673            if let Napi::Threaded(val) = attr? {
1674                return Ok(val);
1675            }
1676        }
1677        Err(ErrorContext::new_missing(
1678            "Napi",
1679            "Threaded",
1680            self.orig_loc,
1681            self.buf.as_ptr() as usize,
1682        ))
1683    }
1684}
1685impl Napi {
1686    pub fn new<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
1687        IterableNapi::with_loc(buf, buf.as_ptr() as usize)
1688    }
1689    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1690        let res = match r#type {
1691            1u16 => "Ifindex",
1692            2u16 => "Id",
1693            3u16 => "Irq",
1694            4u16 => "Pid",
1695            5u16 => "DeferHardIrqs",
1696            6u16 => "GroFlushTimeout",
1697            7u16 => "IrqSuspendTimeout",
1698            8u16 => "Threaded",
1699            _ => return None,
1700        };
1701        Some(res)
1702    }
1703}
1704#[derive(Clone, Copy, Default)]
1705pub struct IterableNapi<'a> {
1706    buf: &'a [u8],
1707    pos: usize,
1708    orig_loc: usize,
1709}
1710impl<'a> IterableNapi<'a> {
1711    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1712        Self {
1713            buf,
1714            pos: 0,
1715            orig_loc,
1716        }
1717    }
1718    pub fn get_buf(&self) -> &'a [u8] {
1719        self.buf
1720    }
1721}
1722impl<'a> Iterator for IterableNapi<'a> {
1723    type Item = Result<Napi, ErrorContext>;
1724    fn next(&mut self) -> Option<Self::Item> {
1725        if self.buf.len() == self.pos {
1726            return None;
1727        }
1728        let pos = self.pos;
1729        let mut r#type = None;
1730        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1731            r#type = Some(header.r#type);
1732            let res = match header.r#type {
1733                1u16 => Napi::Ifindex({
1734                    let res = parse_u32(next);
1735                    let Some(val) = res else { break };
1736                    val
1737                }),
1738                2u16 => Napi::Id({
1739                    let res = parse_u32(next);
1740                    let Some(val) = res else { break };
1741                    val
1742                }),
1743                3u16 => Napi::Irq({
1744                    let res = parse_u32(next);
1745                    let Some(val) = res else { break };
1746                    val
1747                }),
1748                4u16 => Napi::Pid({
1749                    let res = parse_u32(next);
1750                    let Some(val) = res else { break };
1751                    val
1752                }),
1753                5u16 => Napi::DeferHardIrqs({
1754                    let res = parse_u32(next);
1755                    let Some(val) = res else { break };
1756                    val
1757                }),
1758                6u16 => Napi::GroFlushTimeout({
1759                    let res = parse_u32(next);
1760                    let Some(val) = res else { break };
1761                    val
1762                }),
1763                7u16 => Napi::IrqSuspendTimeout({
1764                    let res = parse_u32(next);
1765                    let Some(val) = res else { break };
1766                    val
1767                }),
1768                8u16 => Napi::Threaded({
1769                    let res = parse_u32(next);
1770                    let Some(val) = res else { break };
1771                    val
1772                }),
1773                n => {
1774                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
1775                        break;
1776                    } else {
1777                        continue;
1778                    }
1779                }
1780            };
1781            return Some(Ok(res));
1782        }
1783        Some(Err(ErrorContext::new(
1784            "Napi",
1785            r#type.and_then(|t| Napi::attr_from_type(t)),
1786            self.orig_loc,
1787            self.buf.as_ptr().wrapping_add(pos) as usize,
1788        )))
1789    }
1790}
1791impl std::fmt::Debug for IterableNapi<'_> {
1792    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1793        let mut fmt = f.debug_struct("Napi");
1794        for attr in self.clone() {
1795            let attr = match attr {
1796                Ok(a) => a,
1797                Err(err) => {
1798                    fmt.finish()?;
1799                    f.write_str("Err(")?;
1800                    err.fmt(f)?;
1801                    return f.write_str(")");
1802                }
1803            };
1804            match attr {
1805                Napi::Ifindex(val) => fmt.field("Ifindex", &val),
1806                Napi::Id(val) => fmt.field("Id", &val),
1807                Napi::Irq(val) => fmt.field("Irq", &val),
1808                Napi::Pid(val) => fmt.field("Pid", &val),
1809                Napi::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
1810                Napi::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
1811                Napi::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
1812                Napi::Threaded(val) => fmt.field(
1813                    "Threaded",
1814                    &FormatEnum(val.into(), NapiThreaded::from_value),
1815                ),
1816            };
1817        }
1818        fmt.finish()
1819    }
1820}
1821impl IterableNapi<'_> {
1822    pub fn lookup_attr(
1823        &self,
1824        offset: usize,
1825        missing_type: Option<u16>,
1826    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1827        let mut stack = Vec::new();
1828        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1829        if cur == offset {
1830            stack.push(("Napi", offset));
1831            return (stack, missing_type.and_then(|t| Napi::attr_from_type(t)));
1832        }
1833        if cur > offset || cur + self.buf.len() < offset {
1834            return (stack, None);
1835        }
1836        let mut attrs = self.clone();
1837        let mut last_off = cur + attrs.pos;
1838        while let Some(attr) = attrs.next() {
1839            let Ok(attr) = attr else { break };
1840            match attr {
1841                Napi::Ifindex(val) => {
1842                    if last_off == offset {
1843                        stack.push(("Ifindex", last_off));
1844                        break;
1845                    }
1846                }
1847                Napi::Id(val) => {
1848                    if last_off == offset {
1849                        stack.push(("Id", last_off));
1850                        break;
1851                    }
1852                }
1853                Napi::Irq(val) => {
1854                    if last_off == offset {
1855                        stack.push(("Irq", last_off));
1856                        break;
1857                    }
1858                }
1859                Napi::Pid(val) => {
1860                    if last_off == offset {
1861                        stack.push(("Pid", last_off));
1862                        break;
1863                    }
1864                }
1865                Napi::DeferHardIrqs(val) => {
1866                    if last_off == offset {
1867                        stack.push(("DeferHardIrqs", last_off));
1868                        break;
1869                    }
1870                }
1871                Napi::GroFlushTimeout(val) => {
1872                    if last_off == offset {
1873                        stack.push(("GroFlushTimeout", last_off));
1874                        break;
1875                    }
1876                }
1877                Napi::IrqSuspendTimeout(val) => {
1878                    if last_off == offset {
1879                        stack.push(("IrqSuspendTimeout", last_off));
1880                        break;
1881                    }
1882                }
1883                Napi::Threaded(val) => {
1884                    if last_off == offset {
1885                        stack.push(("Threaded", last_off));
1886                        break;
1887                    }
1888                }
1889                _ => {}
1890            };
1891            last_off = cur + attrs.pos;
1892        }
1893        if !stack.is_empty() {
1894            stack.push(("Napi", cur));
1895        }
1896        (stack, None)
1897    }
1898}
1899#[derive(Clone)]
1900pub enum XskInfo {}
1901impl<'a> IterableXskInfo<'a> {}
1902impl XskInfo {
1903    pub fn new<'a>(buf: &'a [u8]) -> IterableXskInfo<'a> {
1904        IterableXskInfo::with_loc(buf, buf.as_ptr() as usize)
1905    }
1906    fn attr_from_type(r#type: u16) -> Option<&'static str> {
1907        None
1908    }
1909}
1910#[derive(Clone, Copy, Default)]
1911pub struct IterableXskInfo<'a> {
1912    buf: &'a [u8],
1913    pos: usize,
1914    orig_loc: usize,
1915}
1916impl<'a> IterableXskInfo<'a> {
1917    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1918        Self {
1919            buf,
1920            pos: 0,
1921            orig_loc,
1922        }
1923    }
1924    pub fn get_buf(&self) -> &'a [u8] {
1925        self.buf
1926    }
1927}
1928impl<'a> Iterator for IterableXskInfo<'a> {
1929    type Item = Result<XskInfo, ErrorContext>;
1930    fn next(&mut self) -> Option<Self::Item> {
1931        if self.buf.len() == self.pos {
1932            return None;
1933        }
1934        let pos = self.pos;
1935        let mut r#type = None;
1936        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1937            r#type = Some(header.r#type);
1938            let res = match header.r#type {
1939                n => {
1940                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
1941                        break;
1942                    } else {
1943                        continue;
1944                    }
1945                }
1946            };
1947            return Some(Ok(res));
1948        }
1949        Some(Err(ErrorContext::new(
1950            "XskInfo",
1951            r#type.and_then(|t| XskInfo::attr_from_type(t)),
1952            self.orig_loc,
1953            self.buf.as_ptr().wrapping_add(pos) as usize,
1954        )))
1955    }
1956}
1957impl std::fmt::Debug for IterableXskInfo<'_> {
1958    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1959        let mut fmt = f.debug_struct("XskInfo");
1960        for attr in self.clone() {
1961            let attr = match attr {
1962                Ok(a) => a,
1963                Err(err) => {
1964                    fmt.finish()?;
1965                    f.write_str("Err(")?;
1966                    err.fmt(f)?;
1967                    return f.write_str(")");
1968                }
1969            };
1970            match attr {};
1971        }
1972        fmt.finish()
1973    }
1974}
1975impl IterableXskInfo<'_> {
1976    pub fn lookup_attr(
1977        &self,
1978        offset: usize,
1979        missing_type: Option<u16>,
1980    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1981        let mut stack = Vec::new();
1982        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1983        if cur == offset {
1984            stack.push(("XskInfo", offset));
1985            return (stack, missing_type.and_then(|t| XskInfo::attr_from_type(t)));
1986        }
1987        (stack, None)
1988    }
1989}
1990#[derive(Clone)]
1991pub enum Queue<'a> {
1992    #[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."]
1993    Id(u32),
1994    #[doc = "ifindex of the netdevice to which the queue belongs."]
1995    Ifindex(u32),
1996    #[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)"]
1997    Type(u32),
1998    #[doc = "ID of the NAPI instance which services this queue."]
1999    NapiId(u32),
2000    #[doc = "ID of the dmabuf attached to this queue, if any."]
2001    Dmabuf(u32),
2002    #[doc = "io_uring memory provider information."]
2003    IoUring(IterableIoUringProviderInfo<'a>),
2004    #[doc = "XSK information for this queue, if any."]
2005    Xsk(IterableXskInfo<'a>),
2006}
2007impl<'a> IterableQueue<'a> {
2008    #[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."]
2009    pub fn get_id(&self) -> Result<u32, ErrorContext> {
2010        let mut iter = self.clone();
2011        iter.pos = 0;
2012        for attr in iter {
2013            if let Queue::Id(val) = attr? {
2014                return Ok(val);
2015            }
2016        }
2017        Err(ErrorContext::new_missing(
2018            "Queue",
2019            "Id",
2020            self.orig_loc,
2021            self.buf.as_ptr() as usize,
2022        ))
2023    }
2024    #[doc = "ifindex of the netdevice to which the queue belongs."]
2025    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2026        let mut iter = self.clone();
2027        iter.pos = 0;
2028        for attr in iter {
2029            if let Queue::Ifindex(val) = attr? {
2030                return Ok(val);
2031            }
2032        }
2033        Err(ErrorContext::new_missing(
2034            "Queue",
2035            "Ifindex",
2036            self.orig_loc,
2037            self.buf.as_ptr() as usize,
2038        ))
2039    }
2040    #[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)"]
2041    pub fn get_type(&self) -> Result<u32, ErrorContext> {
2042        let mut iter = self.clone();
2043        iter.pos = 0;
2044        for attr in iter {
2045            if let Queue::Type(val) = attr? {
2046                return Ok(val);
2047            }
2048        }
2049        Err(ErrorContext::new_missing(
2050            "Queue",
2051            "Type",
2052            self.orig_loc,
2053            self.buf.as_ptr() as usize,
2054        ))
2055    }
2056    #[doc = "ID of the NAPI instance which services this queue."]
2057    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
2058        let mut iter = self.clone();
2059        iter.pos = 0;
2060        for attr in iter {
2061            if let Queue::NapiId(val) = attr? {
2062                return Ok(val);
2063            }
2064        }
2065        Err(ErrorContext::new_missing(
2066            "Queue",
2067            "NapiId",
2068            self.orig_loc,
2069            self.buf.as_ptr() as usize,
2070        ))
2071    }
2072    #[doc = "ID of the dmabuf attached to this queue, if any."]
2073    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
2074        let mut iter = self.clone();
2075        iter.pos = 0;
2076        for attr in iter {
2077            if let Queue::Dmabuf(val) = attr? {
2078                return Ok(val);
2079            }
2080        }
2081        Err(ErrorContext::new_missing(
2082            "Queue",
2083            "Dmabuf",
2084            self.orig_loc,
2085            self.buf.as_ptr() as usize,
2086        ))
2087    }
2088    #[doc = "io_uring memory provider information."]
2089    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
2090        let mut iter = self.clone();
2091        iter.pos = 0;
2092        for attr in iter {
2093            if let Queue::IoUring(val) = attr? {
2094                return Ok(val);
2095            }
2096        }
2097        Err(ErrorContext::new_missing(
2098            "Queue",
2099            "IoUring",
2100            self.orig_loc,
2101            self.buf.as_ptr() as usize,
2102        ))
2103    }
2104    #[doc = "XSK information for this queue, if any."]
2105    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
2106        let mut iter = self.clone();
2107        iter.pos = 0;
2108        for attr in iter {
2109            if let Queue::Xsk(val) = attr? {
2110                return Ok(val);
2111            }
2112        }
2113        Err(ErrorContext::new_missing(
2114            "Queue",
2115            "Xsk",
2116            self.orig_loc,
2117            self.buf.as_ptr() as usize,
2118        ))
2119    }
2120}
2121impl Queue<'_> {
2122    pub fn new<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
2123        IterableQueue::with_loc(buf, buf.as_ptr() as usize)
2124    }
2125    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2126        let res = match r#type {
2127            1u16 => "Id",
2128            2u16 => "Ifindex",
2129            3u16 => "Type",
2130            4u16 => "NapiId",
2131            5u16 => "Dmabuf",
2132            6u16 => "IoUring",
2133            7u16 => "Xsk",
2134            _ => return None,
2135        };
2136        Some(res)
2137    }
2138}
2139#[derive(Clone, Copy, Default)]
2140pub struct IterableQueue<'a> {
2141    buf: &'a [u8],
2142    pos: usize,
2143    orig_loc: usize,
2144}
2145impl<'a> IterableQueue<'a> {
2146    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2147        Self {
2148            buf,
2149            pos: 0,
2150            orig_loc,
2151        }
2152    }
2153    pub fn get_buf(&self) -> &'a [u8] {
2154        self.buf
2155    }
2156}
2157impl<'a> Iterator for IterableQueue<'a> {
2158    type Item = Result<Queue<'a>, ErrorContext>;
2159    fn next(&mut self) -> Option<Self::Item> {
2160        if self.buf.len() == self.pos {
2161            return None;
2162        }
2163        let pos = self.pos;
2164        let mut r#type = None;
2165        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2166            r#type = Some(header.r#type);
2167            let res = match header.r#type {
2168                1u16 => Queue::Id({
2169                    let res = parse_u32(next);
2170                    let Some(val) = res else { break };
2171                    val
2172                }),
2173                2u16 => Queue::Ifindex({
2174                    let res = parse_u32(next);
2175                    let Some(val) = res else { break };
2176                    val
2177                }),
2178                3u16 => Queue::Type({
2179                    let res = parse_u32(next);
2180                    let Some(val) = res else { break };
2181                    val
2182                }),
2183                4u16 => Queue::NapiId({
2184                    let res = parse_u32(next);
2185                    let Some(val) = res else { break };
2186                    val
2187                }),
2188                5u16 => Queue::Dmabuf({
2189                    let res = parse_u32(next);
2190                    let Some(val) = res else { break };
2191                    val
2192                }),
2193                6u16 => Queue::IoUring({
2194                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
2195                    let Some(val) = res else { break };
2196                    val
2197                }),
2198                7u16 => Queue::Xsk({
2199                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
2200                    let Some(val) = res else { break };
2201                    val
2202                }),
2203                n => {
2204                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
2205                        break;
2206                    } else {
2207                        continue;
2208                    }
2209                }
2210            };
2211            return Some(Ok(res));
2212        }
2213        Some(Err(ErrorContext::new(
2214            "Queue",
2215            r#type.and_then(|t| Queue::attr_from_type(t)),
2216            self.orig_loc,
2217            self.buf.as_ptr().wrapping_add(pos) as usize,
2218        )))
2219    }
2220}
2221impl<'a> std::fmt::Debug for IterableQueue<'_> {
2222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2223        let mut fmt = f.debug_struct("Queue");
2224        for attr in self.clone() {
2225            let attr = match attr {
2226                Ok(a) => a,
2227                Err(err) => {
2228                    fmt.finish()?;
2229                    f.write_str("Err(")?;
2230                    err.fmt(f)?;
2231                    return f.write_str(")");
2232                }
2233            };
2234            match attr {
2235                Queue::Id(val) => fmt.field("Id", &val),
2236                Queue::Ifindex(val) => fmt.field("Ifindex", &val),
2237                Queue::Type(val) => {
2238                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
2239                }
2240                Queue::NapiId(val) => fmt.field("NapiId", &val),
2241                Queue::Dmabuf(val) => fmt.field("Dmabuf", &val),
2242                Queue::IoUring(val) => fmt.field("IoUring", &val),
2243                Queue::Xsk(val) => fmt.field("Xsk", &val),
2244            };
2245        }
2246        fmt.finish()
2247    }
2248}
2249impl IterableQueue<'_> {
2250    pub fn lookup_attr(
2251        &self,
2252        offset: usize,
2253        missing_type: Option<u16>,
2254    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2255        let mut stack = Vec::new();
2256        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2257        if cur == offset {
2258            stack.push(("Queue", offset));
2259            return (stack, missing_type.and_then(|t| Queue::attr_from_type(t)));
2260        }
2261        if cur > offset || cur + self.buf.len() < offset {
2262            return (stack, None);
2263        }
2264        let mut attrs = self.clone();
2265        let mut last_off = cur + attrs.pos;
2266        let mut missing = None;
2267        while let Some(attr) = attrs.next() {
2268            let Ok(attr) = attr else { break };
2269            match attr {
2270                Queue::Id(val) => {
2271                    if last_off == offset {
2272                        stack.push(("Id", last_off));
2273                        break;
2274                    }
2275                }
2276                Queue::Ifindex(val) => {
2277                    if last_off == offset {
2278                        stack.push(("Ifindex", last_off));
2279                        break;
2280                    }
2281                }
2282                Queue::Type(val) => {
2283                    if last_off == offset {
2284                        stack.push(("Type", last_off));
2285                        break;
2286                    }
2287                }
2288                Queue::NapiId(val) => {
2289                    if last_off == offset {
2290                        stack.push(("NapiId", last_off));
2291                        break;
2292                    }
2293                }
2294                Queue::Dmabuf(val) => {
2295                    if last_off == offset {
2296                        stack.push(("Dmabuf", last_off));
2297                        break;
2298                    }
2299                }
2300                Queue::IoUring(val) => {
2301                    (stack, missing) = val.lookup_attr(offset, missing_type);
2302                    if !stack.is_empty() {
2303                        break;
2304                    }
2305                }
2306                Queue::Xsk(val) => {
2307                    (stack, missing) = val.lookup_attr(offset, missing_type);
2308                    if !stack.is_empty() {
2309                        break;
2310                    }
2311                }
2312                _ => {}
2313            };
2314            last_off = cur + attrs.pos;
2315        }
2316        if !stack.is_empty() {
2317            stack.push(("Queue", cur));
2318        }
2319        (stack, missing)
2320    }
2321}
2322#[derive(Clone)]
2323pub enum Qstats {
2324    #[doc = "ifindex of the netdevice to which stats belong."]
2325    Ifindex(u32),
2326    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2327    QueueType(u32),
2328    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2329    QueueId(u32),
2330    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2331    Scope(u32),
2332    #[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"]
2333    RxPackets(u32),
2334    #[doc = "Successfully received bytes, see `rx-packets`."]
2335    RxBytes(u32),
2336    #[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"]
2337    TxPackets(u32),
2338    #[doc = "Successfully sent bytes, see `tx-packets`."]
2339    TxBytes(u32),
2340    #[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"]
2341    RxAllocFail(u32),
2342    #[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"]
2343    RxHwDrops(u32),
2344    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2345    RxHwDropOverruns(u32),
2346    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2347    RxCsumComplete(u32),
2348    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2349    RxCsumUnnecessary(u32),
2350    #[doc = "Number of packets that were not checksummed by device."]
2351    RxCsumNone(u32),
2352    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2353    RxCsumBad(u32),
2354    #[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"]
2355    RxHwGroPackets(u32),
2356    #[doc = "See `rx-hw-gro-packets`."]
2357    RxHwGroBytes(u32),
2358    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2359    RxHwGroWirePackets(u32),
2360    #[doc = "See `rx-hw-gro-wire-packets`."]
2361    RxHwGroWireBytes(u32),
2362    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2363    RxHwDropRatelimits(u32),
2364    #[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"]
2365    TxHwDrops(u32),
2366    #[doc = "Number of packets dropped because they were invalid or malformed."]
2367    TxHwDropErrors(u32),
2368    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2369    TxCsumNone(u32),
2370    #[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"]
2371    TxNeedsCsum(u32),
2372    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2373    TxHwGsoPackets(u32),
2374    #[doc = "See `tx-hw-gso-packets`."]
2375    TxHwGsoBytes(u32),
2376    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2377    TxHwGsoWirePackets(u32),
2378    #[doc = "See `tx-hw-gso-wire-packets`."]
2379    TxHwGsoWireBytes(u32),
2380    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2381    TxHwDropRatelimits(u32),
2382    #[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"]
2383    TxStop(u32),
2384    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2385    TxWake(u32),
2386}
2387impl<'a> IterableQstats<'a> {
2388    #[doc = "ifindex of the netdevice to which stats belong."]
2389    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2390        let mut iter = self.clone();
2391        iter.pos = 0;
2392        for attr in iter {
2393            if let Qstats::Ifindex(val) = attr? {
2394                return Ok(val);
2395            }
2396        }
2397        Err(ErrorContext::new_missing(
2398            "Qstats",
2399            "Ifindex",
2400            self.orig_loc,
2401            self.buf.as_ptr() as usize,
2402        ))
2403    }
2404    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2405    pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
2406        let mut iter = self.clone();
2407        iter.pos = 0;
2408        for attr in iter {
2409            if let Qstats::QueueType(val) = attr? {
2410                return Ok(val);
2411            }
2412        }
2413        Err(ErrorContext::new_missing(
2414            "Qstats",
2415            "QueueType",
2416            self.orig_loc,
2417            self.buf.as_ptr() as usize,
2418        ))
2419    }
2420    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2421    pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
2422        let mut iter = self.clone();
2423        iter.pos = 0;
2424        for attr in iter {
2425            if let Qstats::QueueId(val) = attr? {
2426                return Ok(val);
2427            }
2428        }
2429        Err(ErrorContext::new_missing(
2430            "Qstats",
2431            "QueueId",
2432            self.orig_loc,
2433            self.buf.as_ptr() as usize,
2434        ))
2435    }
2436    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2437    pub fn get_scope(&self) -> Result<u32, ErrorContext> {
2438        let mut iter = self.clone();
2439        iter.pos = 0;
2440        for attr in iter {
2441            if let Qstats::Scope(val) = attr? {
2442                return Ok(val);
2443            }
2444        }
2445        Err(ErrorContext::new_missing(
2446            "Qstats",
2447            "Scope",
2448            self.orig_loc,
2449            self.buf.as_ptr() as usize,
2450        ))
2451    }
2452    #[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"]
2453    pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
2454        let mut iter = self.clone();
2455        iter.pos = 0;
2456        for attr in iter {
2457            if let Qstats::RxPackets(val) = attr? {
2458                return Ok(val);
2459            }
2460        }
2461        Err(ErrorContext::new_missing(
2462            "Qstats",
2463            "RxPackets",
2464            self.orig_loc,
2465            self.buf.as_ptr() as usize,
2466        ))
2467    }
2468    #[doc = "Successfully received bytes, see `rx-packets`."]
2469    pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
2470        let mut iter = self.clone();
2471        iter.pos = 0;
2472        for attr in iter {
2473            if let Qstats::RxBytes(val) = attr? {
2474                return Ok(val);
2475            }
2476        }
2477        Err(ErrorContext::new_missing(
2478            "Qstats",
2479            "RxBytes",
2480            self.orig_loc,
2481            self.buf.as_ptr() as usize,
2482        ))
2483    }
2484    #[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"]
2485    pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
2486        let mut iter = self.clone();
2487        iter.pos = 0;
2488        for attr in iter {
2489            if let Qstats::TxPackets(val) = attr? {
2490                return Ok(val);
2491            }
2492        }
2493        Err(ErrorContext::new_missing(
2494            "Qstats",
2495            "TxPackets",
2496            self.orig_loc,
2497            self.buf.as_ptr() as usize,
2498        ))
2499    }
2500    #[doc = "Successfully sent bytes, see `tx-packets`."]
2501    pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
2502        let mut iter = self.clone();
2503        iter.pos = 0;
2504        for attr in iter {
2505            if let Qstats::TxBytes(val) = attr? {
2506                return Ok(val);
2507            }
2508        }
2509        Err(ErrorContext::new_missing(
2510            "Qstats",
2511            "TxBytes",
2512            self.orig_loc,
2513            self.buf.as_ptr() as usize,
2514        ))
2515    }
2516    #[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"]
2517    pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
2518        let mut iter = self.clone();
2519        iter.pos = 0;
2520        for attr in iter {
2521            if let Qstats::RxAllocFail(val) = attr? {
2522                return Ok(val);
2523            }
2524        }
2525        Err(ErrorContext::new_missing(
2526            "Qstats",
2527            "RxAllocFail",
2528            self.orig_loc,
2529            self.buf.as_ptr() as usize,
2530        ))
2531    }
2532    #[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"]
2533    pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
2534        let mut iter = self.clone();
2535        iter.pos = 0;
2536        for attr in iter {
2537            if let Qstats::RxHwDrops(val) = attr? {
2538                return Ok(val);
2539            }
2540        }
2541        Err(ErrorContext::new_missing(
2542            "Qstats",
2543            "RxHwDrops",
2544            self.orig_loc,
2545            self.buf.as_ptr() as usize,
2546        ))
2547    }
2548    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2549    pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
2550        let mut iter = self.clone();
2551        iter.pos = 0;
2552        for attr in iter {
2553            if let Qstats::RxHwDropOverruns(val) = attr? {
2554                return Ok(val);
2555            }
2556        }
2557        Err(ErrorContext::new_missing(
2558            "Qstats",
2559            "RxHwDropOverruns",
2560            self.orig_loc,
2561            self.buf.as_ptr() as usize,
2562        ))
2563    }
2564    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2565    pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
2566        let mut iter = self.clone();
2567        iter.pos = 0;
2568        for attr in iter {
2569            if let Qstats::RxCsumComplete(val) = attr? {
2570                return Ok(val);
2571            }
2572        }
2573        Err(ErrorContext::new_missing(
2574            "Qstats",
2575            "RxCsumComplete",
2576            self.orig_loc,
2577            self.buf.as_ptr() as usize,
2578        ))
2579    }
2580    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2581    pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
2582        let mut iter = self.clone();
2583        iter.pos = 0;
2584        for attr in iter {
2585            if let Qstats::RxCsumUnnecessary(val) = attr? {
2586                return Ok(val);
2587            }
2588        }
2589        Err(ErrorContext::new_missing(
2590            "Qstats",
2591            "RxCsumUnnecessary",
2592            self.orig_loc,
2593            self.buf.as_ptr() as usize,
2594        ))
2595    }
2596    #[doc = "Number of packets that were not checksummed by device."]
2597    pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
2598        let mut iter = self.clone();
2599        iter.pos = 0;
2600        for attr in iter {
2601            if let Qstats::RxCsumNone(val) = attr? {
2602                return Ok(val);
2603            }
2604        }
2605        Err(ErrorContext::new_missing(
2606            "Qstats",
2607            "RxCsumNone",
2608            self.orig_loc,
2609            self.buf.as_ptr() as usize,
2610        ))
2611    }
2612    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2613    pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
2614        let mut iter = self.clone();
2615        iter.pos = 0;
2616        for attr in iter {
2617            if let Qstats::RxCsumBad(val) = attr? {
2618                return Ok(val);
2619            }
2620        }
2621        Err(ErrorContext::new_missing(
2622            "Qstats",
2623            "RxCsumBad",
2624            self.orig_loc,
2625            self.buf.as_ptr() as usize,
2626        ))
2627    }
2628    #[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"]
2629    pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
2630        let mut iter = self.clone();
2631        iter.pos = 0;
2632        for attr in iter {
2633            if let Qstats::RxHwGroPackets(val) = attr? {
2634                return Ok(val);
2635            }
2636        }
2637        Err(ErrorContext::new_missing(
2638            "Qstats",
2639            "RxHwGroPackets",
2640            self.orig_loc,
2641            self.buf.as_ptr() as usize,
2642        ))
2643    }
2644    #[doc = "See `rx-hw-gro-packets`."]
2645    pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
2646        let mut iter = self.clone();
2647        iter.pos = 0;
2648        for attr in iter {
2649            if let Qstats::RxHwGroBytes(val) = attr? {
2650                return Ok(val);
2651            }
2652        }
2653        Err(ErrorContext::new_missing(
2654            "Qstats",
2655            "RxHwGroBytes",
2656            self.orig_loc,
2657            self.buf.as_ptr() as usize,
2658        ))
2659    }
2660    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2661    pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
2662        let mut iter = self.clone();
2663        iter.pos = 0;
2664        for attr in iter {
2665            if let Qstats::RxHwGroWirePackets(val) = attr? {
2666                return Ok(val);
2667            }
2668        }
2669        Err(ErrorContext::new_missing(
2670            "Qstats",
2671            "RxHwGroWirePackets",
2672            self.orig_loc,
2673            self.buf.as_ptr() as usize,
2674        ))
2675    }
2676    #[doc = "See `rx-hw-gro-wire-packets`."]
2677    pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
2678        let mut iter = self.clone();
2679        iter.pos = 0;
2680        for attr in iter {
2681            if let Qstats::RxHwGroWireBytes(val) = attr? {
2682                return Ok(val);
2683            }
2684        }
2685        Err(ErrorContext::new_missing(
2686            "Qstats",
2687            "RxHwGroWireBytes",
2688            self.orig_loc,
2689            self.buf.as_ptr() as usize,
2690        ))
2691    }
2692    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2693    pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2694        let mut iter = self.clone();
2695        iter.pos = 0;
2696        for attr in iter {
2697            if let Qstats::RxHwDropRatelimits(val) = attr? {
2698                return Ok(val);
2699            }
2700        }
2701        Err(ErrorContext::new_missing(
2702            "Qstats",
2703            "RxHwDropRatelimits",
2704            self.orig_loc,
2705            self.buf.as_ptr() as usize,
2706        ))
2707    }
2708    #[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"]
2709    pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
2710        let mut iter = self.clone();
2711        iter.pos = 0;
2712        for attr in iter {
2713            if let Qstats::TxHwDrops(val) = attr? {
2714                return Ok(val);
2715            }
2716        }
2717        Err(ErrorContext::new_missing(
2718            "Qstats",
2719            "TxHwDrops",
2720            self.orig_loc,
2721            self.buf.as_ptr() as usize,
2722        ))
2723    }
2724    #[doc = "Number of packets dropped because they were invalid or malformed."]
2725    pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
2726        let mut iter = self.clone();
2727        iter.pos = 0;
2728        for attr in iter {
2729            if let Qstats::TxHwDropErrors(val) = attr? {
2730                return Ok(val);
2731            }
2732        }
2733        Err(ErrorContext::new_missing(
2734            "Qstats",
2735            "TxHwDropErrors",
2736            self.orig_loc,
2737            self.buf.as_ptr() as usize,
2738        ))
2739    }
2740    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2741    pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
2742        let mut iter = self.clone();
2743        iter.pos = 0;
2744        for attr in iter {
2745            if let Qstats::TxCsumNone(val) = attr? {
2746                return Ok(val);
2747            }
2748        }
2749        Err(ErrorContext::new_missing(
2750            "Qstats",
2751            "TxCsumNone",
2752            self.orig_loc,
2753            self.buf.as_ptr() as usize,
2754        ))
2755    }
2756    #[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"]
2757    pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
2758        let mut iter = self.clone();
2759        iter.pos = 0;
2760        for attr in iter {
2761            if let Qstats::TxNeedsCsum(val) = attr? {
2762                return Ok(val);
2763            }
2764        }
2765        Err(ErrorContext::new_missing(
2766            "Qstats",
2767            "TxNeedsCsum",
2768            self.orig_loc,
2769            self.buf.as_ptr() as usize,
2770        ))
2771    }
2772    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2773    pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
2774        let mut iter = self.clone();
2775        iter.pos = 0;
2776        for attr in iter {
2777            if let Qstats::TxHwGsoPackets(val) = attr? {
2778                return Ok(val);
2779            }
2780        }
2781        Err(ErrorContext::new_missing(
2782            "Qstats",
2783            "TxHwGsoPackets",
2784            self.orig_loc,
2785            self.buf.as_ptr() as usize,
2786        ))
2787    }
2788    #[doc = "See `tx-hw-gso-packets`."]
2789    pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
2790        let mut iter = self.clone();
2791        iter.pos = 0;
2792        for attr in iter {
2793            if let Qstats::TxHwGsoBytes(val) = attr? {
2794                return Ok(val);
2795            }
2796        }
2797        Err(ErrorContext::new_missing(
2798            "Qstats",
2799            "TxHwGsoBytes",
2800            self.orig_loc,
2801            self.buf.as_ptr() as usize,
2802        ))
2803    }
2804    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2805    pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
2806        let mut iter = self.clone();
2807        iter.pos = 0;
2808        for attr in iter {
2809            if let Qstats::TxHwGsoWirePackets(val) = attr? {
2810                return Ok(val);
2811            }
2812        }
2813        Err(ErrorContext::new_missing(
2814            "Qstats",
2815            "TxHwGsoWirePackets",
2816            self.orig_loc,
2817            self.buf.as_ptr() as usize,
2818        ))
2819    }
2820    #[doc = "See `tx-hw-gso-wire-packets`."]
2821    pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
2822        let mut iter = self.clone();
2823        iter.pos = 0;
2824        for attr in iter {
2825            if let Qstats::TxHwGsoWireBytes(val) = attr? {
2826                return Ok(val);
2827            }
2828        }
2829        Err(ErrorContext::new_missing(
2830            "Qstats",
2831            "TxHwGsoWireBytes",
2832            self.orig_loc,
2833            self.buf.as_ptr() as usize,
2834        ))
2835    }
2836    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2837    pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2838        let mut iter = self.clone();
2839        iter.pos = 0;
2840        for attr in iter {
2841            if let Qstats::TxHwDropRatelimits(val) = attr? {
2842                return Ok(val);
2843            }
2844        }
2845        Err(ErrorContext::new_missing(
2846            "Qstats",
2847            "TxHwDropRatelimits",
2848            self.orig_loc,
2849            self.buf.as_ptr() as usize,
2850        ))
2851    }
2852    #[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"]
2853    pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
2854        let mut iter = self.clone();
2855        iter.pos = 0;
2856        for attr in iter {
2857            if let Qstats::TxStop(val) = attr? {
2858                return Ok(val);
2859            }
2860        }
2861        Err(ErrorContext::new_missing(
2862            "Qstats",
2863            "TxStop",
2864            self.orig_loc,
2865            self.buf.as_ptr() as usize,
2866        ))
2867    }
2868    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2869    pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
2870        let mut iter = self.clone();
2871        iter.pos = 0;
2872        for attr in iter {
2873            if let Qstats::TxWake(val) = attr? {
2874                return Ok(val);
2875            }
2876        }
2877        Err(ErrorContext::new_missing(
2878            "Qstats",
2879            "TxWake",
2880            self.orig_loc,
2881            self.buf.as_ptr() as usize,
2882        ))
2883    }
2884}
2885impl Qstats {
2886    pub fn new<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
2887        IterableQstats::with_loc(buf, buf.as_ptr() as usize)
2888    }
2889    fn attr_from_type(r#type: u16) -> Option<&'static str> {
2890        let res = match r#type {
2891            1u16 => "Ifindex",
2892            2u16 => "QueueType",
2893            3u16 => "QueueId",
2894            4u16 => "Scope",
2895            8u16 => "RxPackets",
2896            9u16 => "RxBytes",
2897            10u16 => "TxPackets",
2898            11u16 => "TxBytes",
2899            12u16 => "RxAllocFail",
2900            13u16 => "RxHwDrops",
2901            14u16 => "RxHwDropOverruns",
2902            15u16 => "RxCsumComplete",
2903            16u16 => "RxCsumUnnecessary",
2904            17u16 => "RxCsumNone",
2905            18u16 => "RxCsumBad",
2906            19u16 => "RxHwGroPackets",
2907            20u16 => "RxHwGroBytes",
2908            21u16 => "RxHwGroWirePackets",
2909            22u16 => "RxHwGroWireBytes",
2910            23u16 => "RxHwDropRatelimits",
2911            24u16 => "TxHwDrops",
2912            25u16 => "TxHwDropErrors",
2913            26u16 => "TxCsumNone",
2914            27u16 => "TxNeedsCsum",
2915            28u16 => "TxHwGsoPackets",
2916            29u16 => "TxHwGsoBytes",
2917            30u16 => "TxHwGsoWirePackets",
2918            31u16 => "TxHwGsoWireBytes",
2919            32u16 => "TxHwDropRatelimits",
2920            33u16 => "TxStop",
2921            34u16 => "TxWake",
2922            _ => return None,
2923        };
2924        Some(res)
2925    }
2926}
2927#[derive(Clone, Copy, Default)]
2928pub struct IterableQstats<'a> {
2929    buf: &'a [u8],
2930    pos: usize,
2931    orig_loc: usize,
2932}
2933impl<'a> IterableQstats<'a> {
2934    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2935        Self {
2936            buf,
2937            pos: 0,
2938            orig_loc,
2939        }
2940    }
2941    pub fn get_buf(&self) -> &'a [u8] {
2942        self.buf
2943    }
2944}
2945impl<'a> Iterator for IterableQstats<'a> {
2946    type Item = Result<Qstats, ErrorContext>;
2947    fn next(&mut self) -> Option<Self::Item> {
2948        if self.buf.len() == self.pos {
2949            return None;
2950        }
2951        let pos = self.pos;
2952        let mut r#type = None;
2953        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2954            r#type = Some(header.r#type);
2955            let res = match header.r#type {
2956                1u16 => Qstats::Ifindex({
2957                    let res = parse_u32(next);
2958                    let Some(val) = res else { break };
2959                    val
2960                }),
2961                2u16 => Qstats::QueueType({
2962                    let res = parse_u32(next);
2963                    let Some(val) = res else { break };
2964                    val
2965                }),
2966                3u16 => Qstats::QueueId({
2967                    let res = parse_u32(next);
2968                    let Some(val) = res else { break };
2969                    val
2970                }),
2971                4u16 => Qstats::Scope({
2972                    let res = parse_u32(next);
2973                    let Some(val) = res else { break };
2974                    val
2975                }),
2976                8u16 => Qstats::RxPackets({
2977                    let res = parse_u32(next);
2978                    let Some(val) = res else { break };
2979                    val
2980                }),
2981                9u16 => Qstats::RxBytes({
2982                    let res = parse_u32(next);
2983                    let Some(val) = res else { break };
2984                    val
2985                }),
2986                10u16 => Qstats::TxPackets({
2987                    let res = parse_u32(next);
2988                    let Some(val) = res else { break };
2989                    val
2990                }),
2991                11u16 => Qstats::TxBytes({
2992                    let res = parse_u32(next);
2993                    let Some(val) = res else { break };
2994                    val
2995                }),
2996                12u16 => Qstats::RxAllocFail({
2997                    let res = parse_u32(next);
2998                    let Some(val) = res else { break };
2999                    val
3000                }),
3001                13u16 => Qstats::RxHwDrops({
3002                    let res = parse_u32(next);
3003                    let Some(val) = res else { break };
3004                    val
3005                }),
3006                14u16 => Qstats::RxHwDropOverruns({
3007                    let res = parse_u32(next);
3008                    let Some(val) = res else { break };
3009                    val
3010                }),
3011                15u16 => Qstats::RxCsumComplete({
3012                    let res = parse_u32(next);
3013                    let Some(val) = res else { break };
3014                    val
3015                }),
3016                16u16 => Qstats::RxCsumUnnecessary({
3017                    let res = parse_u32(next);
3018                    let Some(val) = res else { break };
3019                    val
3020                }),
3021                17u16 => Qstats::RxCsumNone({
3022                    let res = parse_u32(next);
3023                    let Some(val) = res else { break };
3024                    val
3025                }),
3026                18u16 => Qstats::RxCsumBad({
3027                    let res = parse_u32(next);
3028                    let Some(val) = res else { break };
3029                    val
3030                }),
3031                19u16 => Qstats::RxHwGroPackets({
3032                    let res = parse_u32(next);
3033                    let Some(val) = res else { break };
3034                    val
3035                }),
3036                20u16 => Qstats::RxHwGroBytes({
3037                    let res = parse_u32(next);
3038                    let Some(val) = res else { break };
3039                    val
3040                }),
3041                21u16 => Qstats::RxHwGroWirePackets({
3042                    let res = parse_u32(next);
3043                    let Some(val) = res else { break };
3044                    val
3045                }),
3046                22u16 => Qstats::RxHwGroWireBytes({
3047                    let res = parse_u32(next);
3048                    let Some(val) = res else { break };
3049                    val
3050                }),
3051                23u16 => Qstats::RxHwDropRatelimits({
3052                    let res = parse_u32(next);
3053                    let Some(val) = res else { break };
3054                    val
3055                }),
3056                24u16 => Qstats::TxHwDrops({
3057                    let res = parse_u32(next);
3058                    let Some(val) = res else { break };
3059                    val
3060                }),
3061                25u16 => Qstats::TxHwDropErrors({
3062                    let res = parse_u32(next);
3063                    let Some(val) = res else { break };
3064                    val
3065                }),
3066                26u16 => Qstats::TxCsumNone({
3067                    let res = parse_u32(next);
3068                    let Some(val) = res else { break };
3069                    val
3070                }),
3071                27u16 => Qstats::TxNeedsCsum({
3072                    let res = parse_u32(next);
3073                    let Some(val) = res else { break };
3074                    val
3075                }),
3076                28u16 => Qstats::TxHwGsoPackets({
3077                    let res = parse_u32(next);
3078                    let Some(val) = res else { break };
3079                    val
3080                }),
3081                29u16 => Qstats::TxHwGsoBytes({
3082                    let res = parse_u32(next);
3083                    let Some(val) = res else { break };
3084                    val
3085                }),
3086                30u16 => Qstats::TxHwGsoWirePackets({
3087                    let res = parse_u32(next);
3088                    let Some(val) = res else { break };
3089                    val
3090                }),
3091                31u16 => Qstats::TxHwGsoWireBytes({
3092                    let res = parse_u32(next);
3093                    let Some(val) = res else { break };
3094                    val
3095                }),
3096                32u16 => Qstats::TxHwDropRatelimits({
3097                    let res = parse_u32(next);
3098                    let Some(val) = res else { break };
3099                    val
3100                }),
3101                33u16 => Qstats::TxStop({
3102                    let res = parse_u32(next);
3103                    let Some(val) = res else { break };
3104                    val
3105                }),
3106                34u16 => Qstats::TxWake({
3107                    let res = parse_u32(next);
3108                    let Some(val) = res else { break };
3109                    val
3110                }),
3111                n => {
3112                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
3113                        break;
3114                    } else {
3115                        continue;
3116                    }
3117                }
3118            };
3119            return Some(Ok(res));
3120        }
3121        Some(Err(ErrorContext::new(
3122            "Qstats",
3123            r#type.and_then(|t| Qstats::attr_from_type(t)),
3124            self.orig_loc,
3125            self.buf.as_ptr().wrapping_add(pos) as usize,
3126        )))
3127    }
3128}
3129impl std::fmt::Debug for IterableQstats<'_> {
3130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3131        let mut fmt = f.debug_struct("Qstats");
3132        for attr in self.clone() {
3133            let attr = match attr {
3134                Ok(a) => a,
3135                Err(err) => {
3136                    fmt.finish()?;
3137                    f.write_str("Err(")?;
3138                    err.fmt(f)?;
3139                    return f.write_str(")");
3140                }
3141            };
3142            match attr {
3143                Qstats::Ifindex(val) => fmt.field("Ifindex", &val),
3144                Qstats::QueueType(val) => {
3145                    fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
3146                }
3147                Qstats::QueueId(val) => fmt.field("QueueId", &val),
3148                Qstats::Scope(val) => {
3149                    fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
3150                }
3151                Qstats::RxPackets(val) => fmt.field("RxPackets", &val),
3152                Qstats::RxBytes(val) => fmt.field("RxBytes", &val),
3153                Qstats::TxPackets(val) => fmt.field("TxPackets", &val),
3154                Qstats::TxBytes(val) => fmt.field("TxBytes", &val),
3155                Qstats::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
3156                Qstats::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
3157                Qstats::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
3158                Qstats::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
3159                Qstats::RxCsumUnnecessary(val) => fmt.field("RxCsumUnnecessary", &val),
3160                Qstats::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
3161                Qstats::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
3162                Qstats::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
3163                Qstats::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
3164                Qstats::RxHwGroWirePackets(val) => fmt.field("RxHwGroWirePackets", &val),
3165                Qstats::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
3166                Qstats::RxHwDropRatelimits(val) => fmt.field("RxHwDropRatelimits", &val),
3167                Qstats::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
3168                Qstats::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
3169                Qstats::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
3170                Qstats::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
3171                Qstats::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
3172                Qstats::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
3173                Qstats::TxHwGsoWirePackets(val) => fmt.field("TxHwGsoWirePackets", &val),
3174                Qstats::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
3175                Qstats::TxHwDropRatelimits(val) => fmt.field("TxHwDropRatelimits", &val),
3176                Qstats::TxStop(val) => fmt.field("TxStop", &val),
3177                Qstats::TxWake(val) => fmt.field("TxWake", &val),
3178            };
3179        }
3180        fmt.finish()
3181    }
3182}
3183impl IterableQstats<'_> {
3184    pub fn lookup_attr(
3185        &self,
3186        offset: usize,
3187        missing_type: Option<u16>,
3188    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3189        let mut stack = Vec::new();
3190        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3191        if cur == offset {
3192            stack.push(("Qstats", offset));
3193            return (stack, missing_type.and_then(|t| Qstats::attr_from_type(t)));
3194        }
3195        if cur > offset || cur + self.buf.len() < offset {
3196            return (stack, None);
3197        }
3198        let mut attrs = self.clone();
3199        let mut last_off = cur + attrs.pos;
3200        while let Some(attr) = attrs.next() {
3201            let Ok(attr) = attr else { break };
3202            match attr {
3203                Qstats::Ifindex(val) => {
3204                    if last_off == offset {
3205                        stack.push(("Ifindex", last_off));
3206                        break;
3207                    }
3208                }
3209                Qstats::QueueType(val) => {
3210                    if last_off == offset {
3211                        stack.push(("QueueType", last_off));
3212                        break;
3213                    }
3214                }
3215                Qstats::QueueId(val) => {
3216                    if last_off == offset {
3217                        stack.push(("QueueId", last_off));
3218                        break;
3219                    }
3220                }
3221                Qstats::Scope(val) => {
3222                    if last_off == offset {
3223                        stack.push(("Scope", last_off));
3224                        break;
3225                    }
3226                }
3227                Qstats::RxPackets(val) => {
3228                    if last_off == offset {
3229                        stack.push(("RxPackets", last_off));
3230                        break;
3231                    }
3232                }
3233                Qstats::RxBytes(val) => {
3234                    if last_off == offset {
3235                        stack.push(("RxBytes", last_off));
3236                        break;
3237                    }
3238                }
3239                Qstats::TxPackets(val) => {
3240                    if last_off == offset {
3241                        stack.push(("TxPackets", last_off));
3242                        break;
3243                    }
3244                }
3245                Qstats::TxBytes(val) => {
3246                    if last_off == offset {
3247                        stack.push(("TxBytes", last_off));
3248                        break;
3249                    }
3250                }
3251                Qstats::RxAllocFail(val) => {
3252                    if last_off == offset {
3253                        stack.push(("RxAllocFail", last_off));
3254                        break;
3255                    }
3256                }
3257                Qstats::RxHwDrops(val) => {
3258                    if last_off == offset {
3259                        stack.push(("RxHwDrops", last_off));
3260                        break;
3261                    }
3262                }
3263                Qstats::RxHwDropOverruns(val) => {
3264                    if last_off == offset {
3265                        stack.push(("RxHwDropOverruns", last_off));
3266                        break;
3267                    }
3268                }
3269                Qstats::RxCsumComplete(val) => {
3270                    if last_off == offset {
3271                        stack.push(("RxCsumComplete", last_off));
3272                        break;
3273                    }
3274                }
3275                Qstats::RxCsumUnnecessary(val) => {
3276                    if last_off == offset {
3277                        stack.push(("RxCsumUnnecessary", last_off));
3278                        break;
3279                    }
3280                }
3281                Qstats::RxCsumNone(val) => {
3282                    if last_off == offset {
3283                        stack.push(("RxCsumNone", last_off));
3284                        break;
3285                    }
3286                }
3287                Qstats::RxCsumBad(val) => {
3288                    if last_off == offset {
3289                        stack.push(("RxCsumBad", last_off));
3290                        break;
3291                    }
3292                }
3293                Qstats::RxHwGroPackets(val) => {
3294                    if last_off == offset {
3295                        stack.push(("RxHwGroPackets", last_off));
3296                        break;
3297                    }
3298                }
3299                Qstats::RxHwGroBytes(val) => {
3300                    if last_off == offset {
3301                        stack.push(("RxHwGroBytes", last_off));
3302                        break;
3303                    }
3304                }
3305                Qstats::RxHwGroWirePackets(val) => {
3306                    if last_off == offset {
3307                        stack.push(("RxHwGroWirePackets", last_off));
3308                        break;
3309                    }
3310                }
3311                Qstats::RxHwGroWireBytes(val) => {
3312                    if last_off == offset {
3313                        stack.push(("RxHwGroWireBytes", last_off));
3314                        break;
3315                    }
3316                }
3317                Qstats::RxHwDropRatelimits(val) => {
3318                    if last_off == offset {
3319                        stack.push(("RxHwDropRatelimits", last_off));
3320                        break;
3321                    }
3322                }
3323                Qstats::TxHwDrops(val) => {
3324                    if last_off == offset {
3325                        stack.push(("TxHwDrops", last_off));
3326                        break;
3327                    }
3328                }
3329                Qstats::TxHwDropErrors(val) => {
3330                    if last_off == offset {
3331                        stack.push(("TxHwDropErrors", last_off));
3332                        break;
3333                    }
3334                }
3335                Qstats::TxCsumNone(val) => {
3336                    if last_off == offset {
3337                        stack.push(("TxCsumNone", last_off));
3338                        break;
3339                    }
3340                }
3341                Qstats::TxNeedsCsum(val) => {
3342                    if last_off == offset {
3343                        stack.push(("TxNeedsCsum", last_off));
3344                        break;
3345                    }
3346                }
3347                Qstats::TxHwGsoPackets(val) => {
3348                    if last_off == offset {
3349                        stack.push(("TxHwGsoPackets", last_off));
3350                        break;
3351                    }
3352                }
3353                Qstats::TxHwGsoBytes(val) => {
3354                    if last_off == offset {
3355                        stack.push(("TxHwGsoBytes", last_off));
3356                        break;
3357                    }
3358                }
3359                Qstats::TxHwGsoWirePackets(val) => {
3360                    if last_off == offset {
3361                        stack.push(("TxHwGsoWirePackets", last_off));
3362                        break;
3363                    }
3364                }
3365                Qstats::TxHwGsoWireBytes(val) => {
3366                    if last_off == offset {
3367                        stack.push(("TxHwGsoWireBytes", last_off));
3368                        break;
3369                    }
3370                }
3371                Qstats::TxHwDropRatelimits(val) => {
3372                    if last_off == offset {
3373                        stack.push(("TxHwDropRatelimits", last_off));
3374                        break;
3375                    }
3376                }
3377                Qstats::TxStop(val) => {
3378                    if last_off == offset {
3379                        stack.push(("TxStop", last_off));
3380                        break;
3381                    }
3382                }
3383                Qstats::TxWake(val) => {
3384                    if last_off == offset {
3385                        stack.push(("TxWake", last_off));
3386                        break;
3387                    }
3388                }
3389                _ => {}
3390            };
3391            last_off = cur + attrs.pos;
3392        }
3393        if !stack.is_empty() {
3394            stack.push(("Qstats", cur));
3395        }
3396        (stack, None)
3397    }
3398}
3399#[derive(Clone)]
3400pub enum QueueId {
3401    #[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."]
3402    Id(u32),
3403    #[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)"]
3404    Type(u32),
3405}
3406impl<'a> IterableQueueId<'a> {
3407    #[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."]
3408    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3409        let mut iter = self.clone();
3410        iter.pos = 0;
3411        for attr in iter {
3412            if let QueueId::Id(val) = attr? {
3413                return Ok(val);
3414            }
3415        }
3416        Err(ErrorContext::new_missing(
3417            "QueueId",
3418            "Id",
3419            self.orig_loc,
3420            self.buf.as_ptr() as usize,
3421        ))
3422    }
3423    #[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)"]
3424    pub fn get_type(&self) -> Result<u32, ErrorContext> {
3425        let mut iter = self.clone();
3426        iter.pos = 0;
3427        for attr in iter {
3428            if let QueueId::Type(val) = attr? {
3429                return Ok(val);
3430            }
3431        }
3432        Err(ErrorContext::new_missing(
3433            "QueueId",
3434            "Type",
3435            self.orig_loc,
3436            self.buf.as_ptr() as usize,
3437        ))
3438    }
3439}
3440impl QueueId {
3441    pub fn new<'a>(buf: &'a [u8]) -> IterableQueueId<'a> {
3442        IterableQueueId::with_loc(buf, buf.as_ptr() as usize)
3443    }
3444    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3445        Queue::attr_from_type(r#type)
3446    }
3447}
3448#[derive(Clone, Copy, Default)]
3449pub struct IterableQueueId<'a> {
3450    buf: &'a [u8],
3451    pos: usize,
3452    orig_loc: usize,
3453}
3454impl<'a> IterableQueueId<'a> {
3455    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3456        Self {
3457            buf,
3458            pos: 0,
3459            orig_loc,
3460        }
3461    }
3462    pub fn get_buf(&self) -> &'a [u8] {
3463        self.buf
3464    }
3465}
3466impl<'a> Iterator for IterableQueueId<'a> {
3467    type Item = Result<QueueId, ErrorContext>;
3468    fn next(&mut self) -> Option<Self::Item> {
3469        if self.buf.len() == self.pos {
3470            return None;
3471        }
3472        let pos = self.pos;
3473        let mut r#type = None;
3474        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3475            r#type = Some(header.r#type);
3476            let res = match header.r#type {
3477                1u16 => QueueId::Id({
3478                    let res = parse_u32(next);
3479                    let Some(val) = res else { break };
3480                    val
3481                }),
3482                3u16 => QueueId::Type({
3483                    let res = parse_u32(next);
3484                    let Some(val) = res else { break };
3485                    val
3486                }),
3487                n => {
3488                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
3489                        break;
3490                    } else {
3491                        continue;
3492                    }
3493                }
3494            };
3495            return Some(Ok(res));
3496        }
3497        Some(Err(ErrorContext::new(
3498            "QueueId",
3499            r#type.and_then(|t| QueueId::attr_from_type(t)),
3500            self.orig_loc,
3501            self.buf.as_ptr().wrapping_add(pos) as usize,
3502        )))
3503    }
3504}
3505impl std::fmt::Debug for IterableQueueId<'_> {
3506    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3507        let mut fmt = f.debug_struct("QueueId");
3508        for attr in self.clone() {
3509            let attr = match attr {
3510                Ok(a) => a,
3511                Err(err) => {
3512                    fmt.finish()?;
3513                    f.write_str("Err(")?;
3514                    err.fmt(f)?;
3515                    return f.write_str(")");
3516                }
3517            };
3518            match attr {
3519                QueueId::Id(val) => fmt.field("Id", &val),
3520                QueueId::Type(val) => {
3521                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
3522                }
3523            };
3524        }
3525        fmt.finish()
3526    }
3527}
3528impl IterableQueueId<'_> {
3529    pub fn lookup_attr(
3530        &self,
3531        offset: usize,
3532        missing_type: Option<u16>,
3533    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3534        let mut stack = Vec::new();
3535        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3536        if cur == offset {
3537            stack.push(("QueueId", offset));
3538            return (stack, missing_type.and_then(|t| QueueId::attr_from_type(t)));
3539        }
3540        if cur > offset || cur + self.buf.len() < offset {
3541            return (stack, None);
3542        }
3543        let mut attrs = self.clone();
3544        let mut last_off = cur + attrs.pos;
3545        while let Some(attr) = attrs.next() {
3546            let Ok(attr) = attr else { break };
3547            match attr {
3548                QueueId::Id(val) => {
3549                    if last_off == offset {
3550                        stack.push(("Id", last_off));
3551                        break;
3552                    }
3553                }
3554                QueueId::Type(val) => {
3555                    if last_off == offset {
3556                        stack.push(("Type", last_off));
3557                        break;
3558                    }
3559                }
3560                _ => {}
3561            };
3562            last_off = cur + attrs.pos;
3563        }
3564        if !stack.is_empty() {
3565            stack.push(("QueueId", cur));
3566        }
3567        (stack, None)
3568    }
3569}
3570#[derive(Clone)]
3571pub enum Dmabuf<'a> {
3572    #[doc = "netdev ifindex to bind the dmabuf to."]
3573    Ifindex(u32),
3574    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3575    Queues(IterableQueueId<'a>),
3576    #[doc = "dmabuf file descriptor to bind."]
3577    Fd(u32),
3578    #[doc = "id of the dmabuf binding"]
3579    Id(u32),
3580}
3581impl<'a> IterableDmabuf<'a> {
3582    #[doc = "netdev ifindex to bind the dmabuf to."]
3583    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3584        let mut iter = self.clone();
3585        iter.pos = 0;
3586        for attr in iter {
3587            if let Dmabuf::Ifindex(val) = attr? {
3588                return Ok(val);
3589            }
3590        }
3591        Err(ErrorContext::new_missing(
3592            "Dmabuf",
3593            "Ifindex",
3594            self.orig_loc,
3595            self.buf.as_ptr() as usize,
3596        ))
3597    }
3598    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3599    pub fn get_queues(&self) -> MultiAttrIterable<Self, Dmabuf<'a>, IterableQueueId<'a>> {
3600        MultiAttrIterable::new(self.clone(), |variant| {
3601            if let Dmabuf::Queues(val) = variant {
3602                Some(val)
3603            } else {
3604                None
3605            }
3606        })
3607    }
3608    #[doc = "dmabuf file descriptor to bind."]
3609    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
3610        let mut iter = self.clone();
3611        iter.pos = 0;
3612        for attr in iter {
3613            if let Dmabuf::Fd(val) = attr? {
3614                return Ok(val);
3615            }
3616        }
3617        Err(ErrorContext::new_missing(
3618            "Dmabuf",
3619            "Fd",
3620            self.orig_loc,
3621            self.buf.as_ptr() as usize,
3622        ))
3623    }
3624    #[doc = "id of the dmabuf binding"]
3625    pub fn get_id(&self) -> Result<u32, ErrorContext> {
3626        let mut iter = self.clone();
3627        iter.pos = 0;
3628        for attr in iter {
3629            if let Dmabuf::Id(val) = attr? {
3630                return Ok(val);
3631            }
3632        }
3633        Err(ErrorContext::new_missing(
3634            "Dmabuf",
3635            "Id",
3636            self.orig_loc,
3637            self.buf.as_ptr() as usize,
3638        ))
3639    }
3640}
3641impl Dmabuf<'_> {
3642    pub fn new<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
3643        IterableDmabuf::with_loc(buf, buf.as_ptr() as usize)
3644    }
3645    fn attr_from_type(r#type: u16) -> Option<&'static str> {
3646        let res = match r#type {
3647            1u16 => "Ifindex",
3648            2u16 => "Queues",
3649            3u16 => "Fd",
3650            4u16 => "Id",
3651            _ => return None,
3652        };
3653        Some(res)
3654    }
3655}
3656#[derive(Clone, Copy, Default)]
3657pub struct IterableDmabuf<'a> {
3658    buf: &'a [u8],
3659    pos: usize,
3660    orig_loc: usize,
3661}
3662impl<'a> IterableDmabuf<'a> {
3663    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3664        Self {
3665            buf,
3666            pos: 0,
3667            orig_loc,
3668        }
3669    }
3670    pub fn get_buf(&self) -> &'a [u8] {
3671        self.buf
3672    }
3673}
3674impl<'a> Iterator for IterableDmabuf<'a> {
3675    type Item = Result<Dmabuf<'a>, ErrorContext>;
3676    fn next(&mut self) -> Option<Self::Item> {
3677        if self.buf.len() == self.pos {
3678            return None;
3679        }
3680        let pos = self.pos;
3681        let mut r#type = None;
3682        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3683            r#type = Some(header.r#type);
3684            let res = match header.r#type {
3685                1u16 => Dmabuf::Ifindex({
3686                    let res = parse_u32(next);
3687                    let Some(val) = res else { break };
3688                    val
3689                }),
3690                2u16 => Dmabuf::Queues({
3691                    let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3692                    let Some(val) = res else { break };
3693                    val
3694                }),
3695                3u16 => Dmabuf::Fd({
3696                    let res = parse_u32(next);
3697                    let Some(val) = res else { break };
3698                    val
3699                }),
3700                4u16 => Dmabuf::Id({
3701                    let res = parse_u32(next);
3702                    let Some(val) = res else { break };
3703                    val
3704                }),
3705                n => {
3706                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
3707                        break;
3708                    } else {
3709                        continue;
3710                    }
3711                }
3712            };
3713            return Some(Ok(res));
3714        }
3715        Some(Err(ErrorContext::new(
3716            "Dmabuf",
3717            r#type.and_then(|t| Dmabuf::attr_from_type(t)),
3718            self.orig_loc,
3719            self.buf.as_ptr().wrapping_add(pos) as usize,
3720        )))
3721    }
3722}
3723impl<'a> std::fmt::Debug for IterableDmabuf<'_> {
3724    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3725        let mut fmt = f.debug_struct("Dmabuf");
3726        for attr in self.clone() {
3727            let attr = match attr {
3728                Ok(a) => a,
3729                Err(err) => {
3730                    fmt.finish()?;
3731                    f.write_str("Err(")?;
3732                    err.fmt(f)?;
3733                    return f.write_str(")");
3734                }
3735            };
3736            match attr {
3737                Dmabuf::Ifindex(val) => fmt.field("Ifindex", &val),
3738                Dmabuf::Queues(val) => fmt.field("Queues", &val),
3739                Dmabuf::Fd(val) => fmt.field("Fd", &val),
3740                Dmabuf::Id(val) => fmt.field("Id", &val),
3741            };
3742        }
3743        fmt.finish()
3744    }
3745}
3746impl IterableDmabuf<'_> {
3747    pub fn lookup_attr(
3748        &self,
3749        offset: usize,
3750        missing_type: Option<u16>,
3751    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3752        let mut stack = Vec::new();
3753        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3754        if cur == offset {
3755            stack.push(("Dmabuf", offset));
3756            return (stack, missing_type.and_then(|t| Dmabuf::attr_from_type(t)));
3757        }
3758        if cur > offset || cur + self.buf.len() < offset {
3759            return (stack, None);
3760        }
3761        let mut attrs = self.clone();
3762        let mut last_off = cur + attrs.pos;
3763        let mut missing = None;
3764        while let Some(attr) = attrs.next() {
3765            let Ok(attr) = attr else { break };
3766            match attr {
3767                Dmabuf::Ifindex(val) => {
3768                    if last_off == offset {
3769                        stack.push(("Ifindex", last_off));
3770                        break;
3771                    }
3772                }
3773                Dmabuf::Queues(val) => {
3774                    (stack, missing) = val.lookup_attr(offset, missing_type);
3775                    if !stack.is_empty() {
3776                        break;
3777                    }
3778                }
3779                Dmabuf::Fd(val) => {
3780                    if last_off == offset {
3781                        stack.push(("Fd", last_off));
3782                        break;
3783                    }
3784                }
3785                Dmabuf::Id(val) => {
3786                    if last_off == offset {
3787                        stack.push(("Id", last_off));
3788                        break;
3789                    }
3790                }
3791                _ => {}
3792            };
3793            last_off = cur + attrs.pos;
3794        }
3795        if !stack.is_empty() {
3796            stack.push(("Dmabuf", cur));
3797        }
3798        (stack, missing)
3799    }
3800}
3801pub struct PushDev<Prev: Rec> {
3802    pub(crate) prev: Option<Prev>,
3803    pub(crate) header_offset: Option<usize>,
3804}
3805impl<Prev: Rec> Rec for PushDev<Prev> {
3806    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3807        self.prev.as_mut().unwrap().as_rec_mut()
3808    }
3809}
3810impl<Prev: Rec> PushDev<Prev> {
3811    pub fn new(prev: Prev) -> Self {
3812        Self {
3813            prev: Some(prev),
3814            header_offset: None,
3815        }
3816    }
3817    pub fn end_nested(mut self) -> Prev {
3818        let mut prev = self.prev.take().unwrap();
3819        if let Some(header_offset) = &self.header_offset {
3820            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3821        }
3822        prev
3823    }
3824    #[doc = "netdev ifindex"]
3825    pub fn push_ifindex(mut self, value: u32) -> Self {
3826        push_header(self.as_rec_mut(), 1u16, 4 as u16);
3827        self.as_rec_mut().extend(value.to_ne_bytes());
3828        self
3829    }
3830    pub fn push_pad(mut self, value: &[u8]) -> Self {
3831        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
3832        self.as_rec_mut().extend(value);
3833        self
3834    }
3835    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
3836    pub fn push_xdp_features(mut self, value: u64) -> Self {
3837        push_header(self.as_rec_mut(), 3u16, 8 as u16);
3838        self.as_rec_mut().extend(value.to_ne_bytes());
3839        self
3840    }
3841    #[doc = "max fragment count supported by ZC driver"]
3842    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
3843        push_header(self.as_rec_mut(), 4u16, 4 as u16);
3844        self.as_rec_mut().extend(value.to_ne_bytes());
3845        self
3846    }
3847    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
3848    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
3849        push_header(self.as_rec_mut(), 5u16, 8 as u16);
3850        self.as_rec_mut().extend(value.to_ne_bytes());
3851        self
3852    }
3853    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
3854    pub fn push_xsk_features(mut self, value: u64) -> Self {
3855        push_header(self.as_rec_mut(), 6u16, 8 as u16);
3856        self.as_rec_mut().extend(value.to_ne_bytes());
3857        self
3858    }
3859}
3860impl<Prev: Rec> Drop for PushDev<Prev> {
3861    fn drop(&mut self) {
3862        if let Some(prev) = &mut self.prev {
3863            if let Some(header_offset) = &self.header_offset {
3864                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3865            }
3866        }
3867    }
3868}
3869pub struct PushIoUringProviderInfo<Prev: Rec> {
3870    pub(crate) prev: Option<Prev>,
3871    pub(crate) header_offset: Option<usize>,
3872}
3873impl<Prev: Rec> Rec for PushIoUringProviderInfo<Prev> {
3874    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3875        self.prev.as_mut().unwrap().as_rec_mut()
3876    }
3877}
3878impl<Prev: Rec> PushIoUringProviderInfo<Prev> {
3879    pub fn new(prev: Prev) -> Self {
3880        Self {
3881            prev: Some(prev),
3882            header_offset: None,
3883        }
3884    }
3885    pub fn end_nested(mut self) -> Prev {
3886        let mut prev = self.prev.take().unwrap();
3887        if let Some(header_offset) = &self.header_offset {
3888            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3889        }
3890        prev
3891    }
3892}
3893impl<Prev: Rec> Drop for PushIoUringProviderInfo<Prev> {
3894    fn drop(&mut self) {
3895        if let Some(prev) = &mut self.prev {
3896            if let Some(header_offset) = &self.header_offset {
3897                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3898            }
3899        }
3900    }
3901}
3902pub struct PushPagePool<Prev: Rec> {
3903    pub(crate) prev: Option<Prev>,
3904    pub(crate) header_offset: Option<usize>,
3905}
3906impl<Prev: Rec> Rec for PushPagePool<Prev> {
3907    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3908        self.prev.as_mut().unwrap().as_rec_mut()
3909    }
3910}
3911impl<Prev: Rec> PushPagePool<Prev> {
3912    pub fn new(prev: Prev) -> Self {
3913        Self {
3914            prev: Some(prev),
3915            header_offset: None,
3916        }
3917    }
3918    pub fn end_nested(mut self) -> Prev {
3919        let mut prev = self.prev.take().unwrap();
3920        if let Some(header_offset) = &self.header_offset {
3921            finalize_nested_header(prev.as_rec_mut(), *header_offset);
3922        }
3923        prev
3924    }
3925    #[doc = "Unique ID of a Page Pool instance."]
3926    pub fn push_id(mut self, value: u32) -> Self {
3927        push_header(self.as_rec_mut(), 1u16, 4 as u16);
3928        self.as_rec_mut().extend(value.to_ne_bytes());
3929        self
3930    }
3931    #[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"]
3932    pub fn push_ifindex(mut self, value: u32) -> Self {
3933        push_header(self.as_rec_mut(), 2u16, 4 as u16);
3934        self.as_rec_mut().extend(value.to_ne_bytes());
3935        self
3936    }
3937    #[doc = "Id of NAPI using this Page Pool instance."]
3938    pub fn push_napi_id(mut self, value: u32) -> Self {
3939        push_header(self.as_rec_mut(), 3u16, 4 as u16);
3940        self.as_rec_mut().extend(value.to_ne_bytes());
3941        self
3942    }
3943    #[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"]
3944    pub fn push_inflight(mut self, value: u32) -> Self {
3945        push_header(self.as_rec_mut(), 4u16, 4 as u16);
3946        self.as_rec_mut().extend(value.to_ne_bytes());
3947        self
3948    }
3949    #[doc = "Amount of memory held by inflight pages.\n"]
3950    pub fn push_inflight_mem(mut self, value: u32) -> Self {
3951        push_header(self.as_rec_mut(), 5u16, 4 as u16);
3952        self.as_rec_mut().extend(value.to_ne_bytes());
3953        self
3954    }
3955    #[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"]
3956    pub fn push_detach_time(mut self, value: u32) -> Self {
3957        push_header(self.as_rec_mut(), 6u16, 4 as u16);
3958        self.as_rec_mut().extend(value.to_ne_bytes());
3959        self
3960    }
3961    #[doc = "ID of the dmabuf this page-pool is attached to."]
3962    pub fn push_dmabuf(mut self, value: u32) -> Self {
3963        push_header(self.as_rec_mut(), 7u16, 4 as u16);
3964        self.as_rec_mut().extend(value.to_ne_bytes());
3965        self
3966    }
3967    #[doc = "io-uring memory provider information."]
3968    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
3969        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
3970        PushIoUringProviderInfo {
3971            prev: Some(self),
3972            header_offset: Some(header_offset),
3973        }
3974    }
3975}
3976impl<Prev: Rec> Drop for PushPagePool<Prev> {
3977    fn drop(&mut self) {
3978        if let Some(prev) = &mut self.prev {
3979            if let Some(header_offset) = &self.header_offset {
3980                finalize_nested_header(prev.as_rec_mut(), *header_offset);
3981            }
3982        }
3983    }
3984}
3985pub struct PushPagePoolInfo<Prev: Rec> {
3986    pub(crate) prev: Option<Prev>,
3987    pub(crate) header_offset: Option<usize>,
3988}
3989impl<Prev: Rec> Rec for PushPagePoolInfo<Prev> {
3990    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3991        self.prev.as_mut().unwrap().as_rec_mut()
3992    }
3993}
3994impl<Prev: Rec> PushPagePoolInfo<Prev> {
3995    pub fn new(prev: Prev) -> Self {
3996        Self {
3997            prev: Some(prev),
3998            header_offset: None,
3999        }
4000    }
4001    pub fn end_nested(mut self) -> Prev {
4002        let mut prev = self.prev.take().unwrap();
4003        if let Some(header_offset) = &self.header_offset {
4004            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4005        }
4006        prev
4007    }
4008    #[doc = "Unique ID of a Page Pool instance."]
4009    pub fn push_id(mut self, value: u32) -> Self {
4010        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4011        self.as_rec_mut().extend(value.to_ne_bytes());
4012        self
4013    }
4014    #[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"]
4015    pub fn push_ifindex(mut self, value: u32) -> Self {
4016        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4017        self.as_rec_mut().extend(value.to_ne_bytes());
4018        self
4019    }
4020}
4021impl<Prev: Rec> Drop for PushPagePoolInfo<Prev> {
4022    fn drop(&mut self) {
4023        if let Some(prev) = &mut self.prev {
4024            if let Some(header_offset) = &self.header_offset {
4025                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4026            }
4027        }
4028    }
4029}
4030pub struct PushPagePoolStats<Prev: Rec> {
4031    pub(crate) prev: Option<Prev>,
4032    pub(crate) header_offset: Option<usize>,
4033}
4034impl<Prev: Rec> Rec for PushPagePoolStats<Prev> {
4035    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4036        self.prev.as_mut().unwrap().as_rec_mut()
4037    }
4038}
4039impl<Prev: Rec> PushPagePoolStats<Prev> {
4040    pub fn new(prev: Prev) -> Self {
4041        Self {
4042            prev: Some(prev),
4043            header_offset: None,
4044        }
4045    }
4046    pub fn end_nested(mut self) -> Prev {
4047        let mut prev = self.prev.take().unwrap();
4048        if let Some(header_offset) = &self.header_offset {
4049            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4050        }
4051        prev
4052    }
4053    #[doc = "Page pool identifying information."]
4054    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
4055        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4056        PushPagePoolInfo {
4057            prev: Some(self),
4058            header_offset: Some(header_offset),
4059        }
4060    }
4061    pub fn push_alloc_fast(mut self, value: u32) -> Self {
4062        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4063        self.as_rec_mut().extend(value.to_ne_bytes());
4064        self
4065    }
4066    pub fn push_alloc_slow(mut self, value: u32) -> Self {
4067        push_header(self.as_rec_mut(), 9u16, 4 as u16);
4068        self.as_rec_mut().extend(value.to_ne_bytes());
4069        self
4070    }
4071    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
4072        push_header(self.as_rec_mut(), 10u16, 4 as u16);
4073        self.as_rec_mut().extend(value.to_ne_bytes());
4074        self
4075    }
4076    pub fn push_alloc_empty(mut self, value: u32) -> Self {
4077        push_header(self.as_rec_mut(), 11u16, 4 as u16);
4078        self.as_rec_mut().extend(value.to_ne_bytes());
4079        self
4080    }
4081    pub fn push_alloc_refill(mut self, value: u32) -> Self {
4082        push_header(self.as_rec_mut(), 12u16, 4 as u16);
4083        self.as_rec_mut().extend(value.to_ne_bytes());
4084        self
4085    }
4086    pub fn push_alloc_waive(mut self, value: u32) -> Self {
4087        push_header(self.as_rec_mut(), 13u16, 4 as u16);
4088        self.as_rec_mut().extend(value.to_ne_bytes());
4089        self
4090    }
4091    pub fn push_recycle_cached(mut self, value: u32) -> Self {
4092        push_header(self.as_rec_mut(), 14u16, 4 as u16);
4093        self.as_rec_mut().extend(value.to_ne_bytes());
4094        self
4095    }
4096    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
4097        push_header(self.as_rec_mut(), 15u16, 4 as u16);
4098        self.as_rec_mut().extend(value.to_ne_bytes());
4099        self
4100    }
4101    pub fn push_recycle_ring(mut self, value: u32) -> Self {
4102        push_header(self.as_rec_mut(), 16u16, 4 as u16);
4103        self.as_rec_mut().extend(value.to_ne_bytes());
4104        self
4105    }
4106    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
4107        push_header(self.as_rec_mut(), 17u16, 4 as u16);
4108        self.as_rec_mut().extend(value.to_ne_bytes());
4109        self
4110    }
4111    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
4112        push_header(self.as_rec_mut(), 18u16, 4 as u16);
4113        self.as_rec_mut().extend(value.to_ne_bytes());
4114        self
4115    }
4116}
4117impl<Prev: Rec> Drop for PushPagePoolStats<Prev> {
4118    fn drop(&mut self) {
4119        if let Some(prev) = &mut self.prev {
4120            if let Some(header_offset) = &self.header_offset {
4121                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4122            }
4123        }
4124    }
4125}
4126pub struct PushNapi<Prev: Rec> {
4127    pub(crate) prev: Option<Prev>,
4128    pub(crate) header_offset: Option<usize>,
4129}
4130impl<Prev: Rec> Rec for PushNapi<Prev> {
4131    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4132        self.prev.as_mut().unwrap().as_rec_mut()
4133    }
4134}
4135impl<Prev: Rec> PushNapi<Prev> {
4136    pub fn new(prev: Prev) -> Self {
4137        Self {
4138            prev: Some(prev),
4139            header_offset: None,
4140        }
4141    }
4142    pub fn end_nested(mut self) -> Prev {
4143        let mut prev = self.prev.take().unwrap();
4144        if let Some(header_offset) = &self.header_offset {
4145            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4146        }
4147        prev
4148    }
4149    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
4150    pub fn push_ifindex(mut self, value: u32) -> Self {
4151        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4152        self.as_rec_mut().extend(value.to_ne_bytes());
4153        self
4154    }
4155    #[doc = "ID of the NAPI instance."]
4156    pub fn push_id(mut self, value: u32) -> Self {
4157        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4158        self.as_rec_mut().extend(value.to_ne_bytes());
4159        self
4160    }
4161    #[doc = "The associated interrupt vector number for the napi"]
4162    pub fn push_irq(mut self, value: u32) -> Self {
4163        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4164        self.as_rec_mut().extend(value.to_ne_bytes());
4165        self
4166    }
4167    #[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."]
4168    pub fn push_pid(mut self, value: u32) -> Self {
4169        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4170        self.as_rec_mut().extend(value.to_ne_bytes());
4171        self
4172    }
4173    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
4174    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
4175        push_header(self.as_rec_mut(), 5u16, 4 as u16);
4176        self.as_rec_mut().extend(value.to_ne_bytes());
4177        self
4178    }
4179    #[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."]
4180    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
4181        push_header(self.as_rec_mut(), 6u16, 4 as u16);
4182        self.as_rec_mut().extend(value.to_ne_bytes());
4183        self
4184    }
4185    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
4186    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
4187        push_header(self.as_rec_mut(), 7u16, 4 as u16);
4188        self.as_rec_mut().extend(value.to_ne_bytes());
4189        self
4190    }
4191    #[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)"]
4192    pub fn push_threaded(mut self, value: u32) -> Self {
4193        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4194        self.as_rec_mut().extend(value.to_ne_bytes());
4195        self
4196    }
4197}
4198impl<Prev: Rec> Drop for PushNapi<Prev> {
4199    fn drop(&mut self) {
4200        if let Some(prev) = &mut self.prev {
4201            if let Some(header_offset) = &self.header_offset {
4202                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4203            }
4204        }
4205    }
4206}
4207pub struct PushXskInfo<Prev: Rec> {
4208    pub(crate) prev: Option<Prev>,
4209    pub(crate) header_offset: Option<usize>,
4210}
4211impl<Prev: Rec> Rec for PushXskInfo<Prev> {
4212    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4213        self.prev.as_mut().unwrap().as_rec_mut()
4214    }
4215}
4216impl<Prev: Rec> PushXskInfo<Prev> {
4217    pub fn new(prev: Prev) -> Self {
4218        Self {
4219            prev: Some(prev),
4220            header_offset: None,
4221        }
4222    }
4223    pub fn end_nested(mut self) -> Prev {
4224        let mut prev = self.prev.take().unwrap();
4225        if let Some(header_offset) = &self.header_offset {
4226            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4227        }
4228        prev
4229    }
4230}
4231impl<Prev: Rec> Drop for PushXskInfo<Prev> {
4232    fn drop(&mut self) {
4233        if let Some(prev) = &mut self.prev {
4234            if let Some(header_offset) = &self.header_offset {
4235                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4236            }
4237        }
4238    }
4239}
4240pub struct PushQueue<Prev: Rec> {
4241    pub(crate) prev: Option<Prev>,
4242    pub(crate) header_offset: Option<usize>,
4243}
4244impl<Prev: Rec> Rec for PushQueue<Prev> {
4245    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4246        self.prev.as_mut().unwrap().as_rec_mut()
4247    }
4248}
4249impl<Prev: Rec> PushQueue<Prev> {
4250    pub fn new(prev: Prev) -> Self {
4251        Self {
4252            prev: Some(prev),
4253            header_offset: None,
4254        }
4255    }
4256    pub fn end_nested(mut self) -> Prev {
4257        let mut prev = self.prev.take().unwrap();
4258        if let Some(header_offset) = &self.header_offset {
4259            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4260        }
4261        prev
4262    }
4263    #[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."]
4264    pub fn push_id(mut self, value: u32) -> Self {
4265        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4266        self.as_rec_mut().extend(value.to_ne_bytes());
4267        self
4268    }
4269    #[doc = "ifindex of the netdevice to which the queue belongs."]
4270    pub fn push_ifindex(mut self, value: u32) -> Self {
4271        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4272        self.as_rec_mut().extend(value.to_ne_bytes());
4273        self
4274    }
4275    #[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)"]
4276    pub fn push_type(mut self, value: u32) -> Self {
4277        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4278        self.as_rec_mut().extend(value.to_ne_bytes());
4279        self
4280    }
4281    #[doc = "ID of the NAPI instance which services this queue."]
4282    pub fn push_napi_id(mut self, value: u32) -> Self {
4283        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4284        self.as_rec_mut().extend(value.to_ne_bytes());
4285        self
4286    }
4287    #[doc = "ID of the dmabuf attached to this queue, if any."]
4288    pub fn push_dmabuf(mut self, value: u32) -> Self {
4289        push_header(self.as_rec_mut(), 5u16, 4 as u16);
4290        self.as_rec_mut().extend(value.to_ne_bytes());
4291        self
4292    }
4293    #[doc = "io_uring memory provider information."]
4294    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4295        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
4296        PushIoUringProviderInfo {
4297            prev: Some(self),
4298            header_offset: Some(header_offset),
4299        }
4300    }
4301    #[doc = "XSK information for this queue, if any."]
4302    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
4303        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
4304        PushXskInfo {
4305            prev: Some(self),
4306            header_offset: Some(header_offset),
4307        }
4308    }
4309}
4310impl<Prev: Rec> Drop for PushQueue<Prev> {
4311    fn drop(&mut self) {
4312        if let Some(prev) = &mut self.prev {
4313            if let Some(header_offset) = &self.header_offset {
4314                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4315            }
4316        }
4317    }
4318}
4319pub struct PushQstats<Prev: Rec> {
4320    pub(crate) prev: Option<Prev>,
4321    pub(crate) header_offset: Option<usize>,
4322}
4323impl<Prev: Rec> Rec for PushQstats<Prev> {
4324    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4325        self.prev.as_mut().unwrap().as_rec_mut()
4326    }
4327}
4328impl<Prev: Rec> PushQstats<Prev> {
4329    pub fn new(prev: Prev) -> Self {
4330        Self {
4331            prev: Some(prev),
4332            header_offset: None,
4333        }
4334    }
4335    pub fn end_nested(mut self) -> Prev {
4336        let mut prev = self.prev.take().unwrap();
4337        if let Some(header_offset) = &self.header_offset {
4338            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4339        }
4340        prev
4341    }
4342    #[doc = "ifindex of the netdevice to which stats belong."]
4343    pub fn push_ifindex(mut self, value: u32) -> Self {
4344        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4345        self.as_rec_mut().extend(value.to_ne_bytes());
4346        self
4347    }
4348    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
4349    pub fn push_queue_type(mut self, value: u32) -> Self {
4350        push_header(self.as_rec_mut(), 2u16, 4 as u16);
4351        self.as_rec_mut().extend(value.to_ne_bytes());
4352        self
4353    }
4354    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
4355    pub fn push_queue_id(mut self, value: u32) -> Self {
4356        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4357        self.as_rec_mut().extend(value.to_ne_bytes());
4358        self
4359    }
4360    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
4361    pub fn push_scope(mut self, value: u32) -> Self {
4362        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4363        self.as_rec_mut().extend(value.to_ne_bytes());
4364        self
4365    }
4366    #[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"]
4367    pub fn push_rx_packets(mut self, value: u32) -> Self {
4368        push_header(self.as_rec_mut(), 8u16, 4 as u16);
4369        self.as_rec_mut().extend(value.to_ne_bytes());
4370        self
4371    }
4372    #[doc = "Successfully received bytes, see `rx-packets`."]
4373    pub fn push_rx_bytes(mut self, value: u32) -> Self {
4374        push_header(self.as_rec_mut(), 9u16, 4 as u16);
4375        self.as_rec_mut().extend(value.to_ne_bytes());
4376        self
4377    }
4378    #[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"]
4379    pub fn push_tx_packets(mut self, value: u32) -> Self {
4380        push_header(self.as_rec_mut(), 10u16, 4 as u16);
4381        self.as_rec_mut().extend(value.to_ne_bytes());
4382        self
4383    }
4384    #[doc = "Successfully sent bytes, see `tx-packets`."]
4385    pub fn push_tx_bytes(mut self, value: u32) -> Self {
4386        push_header(self.as_rec_mut(), 11u16, 4 as u16);
4387        self.as_rec_mut().extend(value.to_ne_bytes());
4388        self
4389    }
4390    #[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"]
4391    pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
4392        push_header(self.as_rec_mut(), 12u16, 4 as u16);
4393        self.as_rec_mut().extend(value.to_ne_bytes());
4394        self
4395    }
4396    #[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"]
4397    pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
4398        push_header(self.as_rec_mut(), 13u16, 4 as u16);
4399        self.as_rec_mut().extend(value.to_ne_bytes());
4400        self
4401    }
4402    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
4403    pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
4404        push_header(self.as_rec_mut(), 14u16, 4 as u16);
4405        self.as_rec_mut().extend(value.to_ne_bytes());
4406        self
4407    }
4408    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
4409    pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
4410        push_header(self.as_rec_mut(), 15u16, 4 as u16);
4411        self.as_rec_mut().extend(value.to_ne_bytes());
4412        self
4413    }
4414    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
4415    pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
4416        push_header(self.as_rec_mut(), 16u16, 4 as u16);
4417        self.as_rec_mut().extend(value.to_ne_bytes());
4418        self
4419    }
4420    #[doc = "Number of packets that were not checksummed by device."]
4421    pub fn push_rx_csum_none(mut self, value: u32) -> Self {
4422        push_header(self.as_rec_mut(), 17u16, 4 as u16);
4423        self.as_rec_mut().extend(value.to_ne_bytes());
4424        self
4425    }
4426    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
4427    pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
4428        push_header(self.as_rec_mut(), 18u16, 4 as u16);
4429        self.as_rec_mut().extend(value.to_ne_bytes());
4430        self
4431    }
4432    #[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"]
4433    pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
4434        push_header(self.as_rec_mut(), 19u16, 4 as u16);
4435        self.as_rec_mut().extend(value.to_ne_bytes());
4436        self
4437    }
4438    #[doc = "See `rx-hw-gro-packets`."]
4439    pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
4440        push_header(self.as_rec_mut(), 20u16, 4 as u16);
4441        self.as_rec_mut().extend(value.to_ne_bytes());
4442        self
4443    }
4444    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
4445    pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
4446        push_header(self.as_rec_mut(), 21u16, 4 as u16);
4447        self.as_rec_mut().extend(value.to_ne_bytes());
4448        self
4449    }
4450    #[doc = "See `rx-hw-gro-wire-packets`."]
4451    pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
4452        push_header(self.as_rec_mut(), 22u16, 4 as u16);
4453        self.as_rec_mut().extend(value.to_ne_bytes());
4454        self
4455    }
4456    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
4457    pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4458        push_header(self.as_rec_mut(), 23u16, 4 as u16);
4459        self.as_rec_mut().extend(value.to_ne_bytes());
4460        self
4461    }
4462    #[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"]
4463    pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
4464        push_header(self.as_rec_mut(), 24u16, 4 as u16);
4465        self.as_rec_mut().extend(value.to_ne_bytes());
4466        self
4467    }
4468    #[doc = "Number of packets dropped because they were invalid or malformed."]
4469    pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
4470        push_header(self.as_rec_mut(), 25u16, 4 as u16);
4471        self.as_rec_mut().extend(value.to_ne_bytes());
4472        self
4473    }
4474    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
4475    pub fn push_tx_csum_none(mut self, value: u32) -> Self {
4476        push_header(self.as_rec_mut(), 26u16, 4 as u16);
4477        self.as_rec_mut().extend(value.to_ne_bytes());
4478        self
4479    }
4480    #[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"]
4481    pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
4482        push_header(self.as_rec_mut(), 27u16, 4 as u16);
4483        self.as_rec_mut().extend(value.to_ne_bytes());
4484        self
4485    }
4486    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
4487    pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
4488        push_header(self.as_rec_mut(), 28u16, 4 as u16);
4489        self.as_rec_mut().extend(value.to_ne_bytes());
4490        self
4491    }
4492    #[doc = "See `tx-hw-gso-packets`."]
4493    pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
4494        push_header(self.as_rec_mut(), 29u16, 4 as u16);
4495        self.as_rec_mut().extend(value.to_ne_bytes());
4496        self
4497    }
4498    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
4499    pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
4500        push_header(self.as_rec_mut(), 30u16, 4 as u16);
4501        self.as_rec_mut().extend(value.to_ne_bytes());
4502        self
4503    }
4504    #[doc = "See `tx-hw-gso-wire-packets`."]
4505    pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
4506        push_header(self.as_rec_mut(), 31u16, 4 as u16);
4507        self.as_rec_mut().extend(value.to_ne_bytes());
4508        self
4509    }
4510    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
4511    pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4512        push_header(self.as_rec_mut(), 32u16, 4 as u16);
4513        self.as_rec_mut().extend(value.to_ne_bytes());
4514        self
4515    }
4516    #[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"]
4517    pub fn push_tx_stop(mut self, value: u32) -> Self {
4518        push_header(self.as_rec_mut(), 33u16, 4 as u16);
4519        self.as_rec_mut().extend(value.to_ne_bytes());
4520        self
4521    }
4522    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
4523    pub fn push_tx_wake(mut self, value: u32) -> Self {
4524        push_header(self.as_rec_mut(), 34u16, 4 as u16);
4525        self.as_rec_mut().extend(value.to_ne_bytes());
4526        self
4527    }
4528}
4529impl<Prev: Rec> Drop for PushQstats<Prev> {
4530    fn drop(&mut self) {
4531        if let Some(prev) = &mut self.prev {
4532            if let Some(header_offset) = &self.header_offset {
4533                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4534            }
4535        }
4536    }
4537}
4538pub struct PushQueueId<Prev: Rec> {
4539    pub(crate) prev: Option<Prev>,
4540    pub(crate) header_offset: Option<usize>,
4541}
4542impl<Prev: Rec> Rec for PushQueueId<Prev> {
4543    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4544        self.prev.as_mut().unwrap().as_rec_mut()
4545    }
4546}
4547impl<Prev: Rec> PushQueueId<Prev> {
4548    pub fn new(prev: Prev) -> Self {
4549        Self {
4550            prev: Some(prev),
4551            header_offset: None,
4552        }
4553    }
4554    pub fn end_nested(mut self) -> Prev {
4555        let mut prev = self.prev.take().unwrap();
4556        if let Some(header_offset) = &self.header_offset {
4557            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4558        }
4559        prev
4560    }
4561    #[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."]
4562    pub fn push_id(mut self, value: u32) -> Self {
4563        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4564        self.as_rec_mut().extend(value.to_ne_bytes());
4565        self
4566    }
4567    #[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)"]
4568    pub fn push_type(mut self, value: u32) -> Self {
4569        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4570        self.as_rec_mut().extend(value.to_ne_bytes());
4571        self
4572    }
4573}
4574impl<Prev: Rec> Drop for PushQueueId<Prev> {
4575    fn drop(&mut self) {
4576        if let Some(prev) = &mut self.prev {
4577            if let Some(header_offset) = &self.header_offset {
4578                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4579            }
4580        }
4581    }
4582}
4583pub struct PushDmabuf<Prev: Rec> {
4584    pub(crate) prev: Option<Prev>,
4585    pub(crate) header_offset: Option<usize>,
4586}
4587impl<Prev: Rec> Rec for PushDmabuf<Prev> {
4588    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4589        self.prev.as_mut().unwrap().as_rec_mut()
4590    }
4591}
4592impl<Prev: Rec> PushDmabuf<Prev> {
4593    pub fn new(prev: Prev) -> Self {
4594        Self {
4595            prev: Some(prev),
4596            header_offset: None,
4597        }
4598    }
4599    pub fn end_nested(mut self) -> Prev {
4600        let mut prev = self.prev.take().unwrap();
4601        if let Some(header_offset) = &self.header_offset {
4602            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4603        }
4604        prev
4605    }
4606    #[doc = "netdev ifindex to bind the dmabuf to."]
4607    pub fn push_ifindex(mut self, value: u32) -> Self {
4608        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4609        self.as_rec_mut().extend(value.to_ne_bytes());
4610        self
4611    }
4612    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
4613    pub fn nested_queues(mut self) -> PushQueueId<Self> {
4614        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4615        PushQueueId {
4616            prev: Some(self),
4617            header_offset: Some(header_offset),
4618        }
4619    }
4620    #[doc = "dmabuf file descriptor to bind."]
4621    pub fn push_fd(mut self, value: u32) -> Self {
4622        push_header(self.as_rec_mut(), 3u16, 4 as u16);
4623        self.as_rec_mut().extend(value.to_ne_bytes());
4624        self
4625    }
4626    #[doc = "id of the dmabuf binding"]
4627    pub fn push_id(mut self, value: u32) -> Self {
4628        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4629        self.as_rec_mut().extend(value.to_ne_bytes());
4630        self
4631    }
4632}
4633impl<Prev: Rec> Drop for PushDmabuf<Prev> {
4634    fn drop(&mut self) {
4635        if let Some(prev) = &mut self.prev {
4636            if let Some(header_offset) = &self.header_offset {
4637                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4638            }
4639        }
4640    }
4641}
4642#[doc = "Get / dump information about a netdev."]
4643pub struct PushOpDevGetDumpRequest<Prev: Rec> {
4644    pub(crate) prev: Option<Prev>,
4645    pub(crate) header_offset: Option<usize>,
4646}
4647impl<Prev: Rec> Rec for PushOpDevGetDumpRequest<Prev> {
4648    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4649        self.prev.as_mut().unwrap().as_rec_mut()
4650    }
4651}
4652impl<Prev: Rec> PushOpDevGetDumpRequest<Prev> {
4653    pub fn new(mut prev: Prev) -> Self {
4654        Self::write_header(&mut prev);
4655        Self::new_without_header(prev)
4656    }
4657    fn new_without_header(prev: Prev) -> Self {
4658        Self {
4659            prev: Some(prev),
4660            header_offset: None,
4661        }
4662    }
4663    fn write_header(prev: &mut Prev) {
4664        let mut header = PushBuiltinNfgenmsg::new();
4665        header.set_cmd(1u8);
4666        header.set_version(1u8);
4667        prev.as_rec_mut().extend(header.as_slice());
4668    }
4669    pub fn end_nested(mut self) -> Prev {
4670        let mut prev = self.prev.take().unwrap();
4671        if let Some(header_offset) = &self.header_offset {
4672            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4673        }
4674        prev
4675    }
4676}
4677impl<Prev: Rec> Drop for PushOpDevGetDumpRequest<Prev> {
4678    fn drop(&mut self) {
4679        if let Some(prev) = &mut self.prev {
4680            if let Some(header_offset) = &self.header_offset {
4681                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4682            }
4683        }
4684    }
4685}
4686#[doc = "Get / dump information about a netdev."]
4687#[derive(Clone)]
4688pub enum OpDevGetDumpRequest {}
4689impl<'a> IterableOpDevGetDumpRequest<'a> {}
4690impl OpDevGetDumpRequest {
4691    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpRequest<'a> {
4692        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4693        IterableOpDevGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
4694    }
4695    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4696        Dev::attr_from_type(r#type)
4697    }
4698}
4699#[derive(Clone, Copy, Default)]
4700pub struct IterableOpDevGetDumpRequest<'a> {
4701    buf: &'a [u8],
4702    pos: usize,
4703    orig_loc: usize,
4704}
4705impl<'a> IterableOpDevGetDumpRequest<'a> {
4706    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4707        Self {
4708            buf,
4709            pos: 0,
4710            orig_loc,
4711        }
4712    }
4713    pub fn get_buf(&self) -> &'a [u8] {
4714        self.buf
4715    }
4716}
4717impl<'a> Iterator for IterableOpDevGetDumpRequest<'a> {
4718    type Item = Result<OpDevGetDumpRequest, ErrorContext>;
4719    fn next(&mut self) -> Option<Self::Item> {
4720        if self.buf.len() == self.pos {
4721            return None;
4722        }
4723        let pos = self.pos;
4724        let mut r#type = None;
4725        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
4726            r#type = Some(header.r#type);
4727            let res = match header.r#type {
4728                n => {
4729                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
4730                        break;
4731                    } else {
4732                        continue;
4733                    }
4734                }
4735            };
4736            return Some(Ok(res));
4737        }
4738        Some(Err(ErrorContext::new(
4739            "OpDevGetDumpRequest",
4740            r#type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4741            self.orig_loc,
4742            self.buf.as_ptr().wrapping_add(pos) as usize,
4743        )))
4744    }
4745}
4746impl std::fmt::Debug for IterableOpDevGetDumpRequest<'_> {
4747    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4748        let mut fmt = f.debug_struct("OpDevGetDumpRequest");
4749        for attr in self.clone() {
4750            let attr = match attr {
4751                Ok(a) => a,
4752                Err(err) => {
4753                    fmt.finish()?;
4754                    f.write_str("Err(")?;
4755                    err.fmt(f)?;
4756                    return f.write_str(")");
4757                }
4758            };
4759            match attr {};
4760        }
4761        fmt.finish()
4762    }
4763}
4764impl IterableOpDevGetDumpRequest<'_> {
4765    pub fn lookup_attr(
4766        &self,
4767        offset: usize,
4768        missing_type: Option<u16>,
4769    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4770        let mut stack = Vec::new();
4771        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4772        if cur == offset + PushBuiltinNfgenmsg::len() {
4773            stack.push(("OpDevGetDumpRequest", offset));
4774            return (
4775                stack,
4776                missing_type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4777            );
4778        }
4779        (stack, None)
4780    }
4781}
4782#[doc = "Get / dump information about a netdev."]
4783pub struct PushOpDevGetDumpReply<Prev: Rec> {
4784    pub(crate) prev: Option<Prev>,
4785    pub(crate) header_offset: Option<usize>,
4786}
4787impl<Prev: Rec> Rec for PushOpDevGetDumpReply<Prev> {
4788    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4789        self.prev.as_mut().unwrap().as_rec_mut()
4790    }
4791}
4792impl<Prev: Rec> PushOpDevGetDumpReply<Prev> {
4793    pub fn new(mut prev: Prev) -> Self {
4794        Self::write_header(&mut prev);
4795        Self::new_without_header(prev)
4796    }
4797    fn new_without_header(prev: Prev) -> Self {
4798        Self {
4799            prev: Some(prev),
4800            header_offset: None,
4801        }
4802    }
4803    fn write_header(prev: &mut Prev) {
4804        let mut header = PushBuiltinNfgenmsg::new();
4805        header.set_cmd(1u8);
4806        header.set_version(1u8);
4807        prev.as_rec_mut().extend(header.as_slice());
4808    }
4809    pub fn end_nested(mut self) -> Prev {
4810        let mut prev = self.prev.take().unwrap();
4811        if let Some(header_offset) = &self.header_offset {
4812            finalize_nested_header(prev.as_rec_mut(), *header_offset);
4813        }
4814        prev
4815    }
4816    #[doc = "netdev ifindex"]
4817    pub fn push_ifindex(mut self, value: u32) -> Self {
4818        push_header(self.as_rec_mut(), 1u16, 4 as u16);
4819        self.as_rec_mut().extend(value.to_ne_bytes());
4820        self
4821    }
4822    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4823    pub fn push_xdp_features(mut self, value: u64) -> Self {
4824        push_header(self.as_rec_mut(), 3u16, 8 as u16);
4825        self.as_rec_mut().extend(value.to_ne_bytes());
4826        self
4827    }
4828    #[doc = "max fragment count supported by ZC driver"]
4829    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
4830        push_header(self.as_rec_mut(), 4u16, 4 as u16);
4831        self.as_rec_mut().extend(value.to_ne_bytes());
4832        self
4833    }
4834    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4835    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
4836        push_header(self.as_rec_mut(), 5u16, 8 as u16);
4837        self.as_rec_mut().extend(value.to_ne_bytes());
4838        self
4839    }
4840    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4841    pub fn push_xsk_features(mut self, value: u64) -> Self {
4842        push_header(self.as_rec_mut(), 6u16, 8 as u16);
4843        self.as_rec_mut().extend(value.to_ne_bytes());
4844        self
4845    }
4846}
4847impl<Prev: Rec> Drop for PushOpDevGetDumpReply<Prev> {
4848    fn drop(&mut self) {
4849        if let Some(prev) = &mut self.prev {
4850            if let Some(header_offset) = &self.header_offset {
4851                finalize_nested_header(prev.as_rec_mut(), *header_offset);
4852            }
4853        }
4854    }
4855}
4856#[doc = "Get / dump information about a netdev."]
4857#[derive(Clone)]
4858pub enum OpDevGetDumpReply {
4859    #[doc = "netdev ifindex"]
4860    Ifindex(u32),
4861    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4862    XdpFeatures(u64),
4863    #[doc = "max fragment count supported by ZC driver"]
4864    XdpZcMaxSegs(u32),
4865    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4866    XdpRxMetadataFeatures(u64),
4867    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4868    XskFeatures(u64),
4869}
4870impl<'a> IterableOpDevGetDumpReply<'a> {
4871    #[doc = "netdev ifindex"]
4872    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
4873        let mut iter = self.clone();
4874        iter.pos = 0;
4875        for attr in iter {
4876            if let OpDevGetDumpReply::Ifindex(val) = attr? {
4877                return Ok(val);
4878            }
4879        }
4880        Err(ErrorContext::new_missing(
4881            "OpDevGetDumpReply",
4882            "Ifindex",
4883            self.orig_loc,
4884            self.buf.as_ptr() as usize,
4885        ))
4886    }
4887    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4888    pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
4889        let mut iter = self.clone();
4890        iter.pos = 0;
4891        for attr in iter {
4892            if let OpDevGetDumpReply::XdpFeatures(val) = attr? {
4893                return Ok(val);
4894            }
4895        }
4896        Err(ErrorContext::new_missing(
4897            "OpDevGetDumpReply",
4898            "XdpFeatures",
4899            self.orig_loc,
4900            self.buf.as_ptr() as usize,
4901        ))
4902    }
4903    #[doc = "max fragment count supported by ZC driver"]
4904    pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
4905        let mut iter = self.clone();
4906        iter.pos = 0;
4907        for attr in iter {
4908            if let OpDevGetDumpReply::XdpZcMaxSegs(val) = attr? {
4909                return Ok(val);
4910            }
4911        }
4912        Err(ErrorContext::new_missing(
4913            "OpDevGetDumpReply",
4914            "XdpZcMaxSegs",
4915            self.orig_loc,
4916            self.buf.as_ptr() as usize,
4917        ))
4918    }
4919    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4920    pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
4921        let mut iter = self.clone();
4922        iter.pos = 0;
4923        for attr in iter {
4924            if let OpDevGetDumpReply::XdpRxMetadataFeatures(val) = attr? {
4925                return Ok(val);
4926            }
4927        }
4928        Err(ErrorContext::new_missing(
4929            "OpDevGetDumpReply",
4930            "XdpRxMetadataFeatures",
4931            self.orig_loc,
4932            self.buf.as_ptr() as usize,
4933        ))
4934    }
4935    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4936    pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
4937        let mut iter = self.clone();
4938        iter.pos = 0;
4939        for attr in iter {
4940            if let OpDevGetDumpReply::XskFeatures(val) = attr? {
4941                return Ok(val);
4942            }
4943        }
4944        Err(ErrorContext::new_missing(
4945            "OpDevGetDumpReply",
4946            "XskFeatures",
4947            self.orig_loc,
4948            self.buf.as_ptr() as usize,
4949        ))
4950    }
4951}
4952impl OpDevGetDumpReply {
4953    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpReply<'a> {
4954        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4955        IterableOpDevGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
4956    }
4957    fn attr_from_type(r#type: u16) -> Option<&'static str> {
4958        Dev::attr_from_type(r#type)
4959    }
4960}
4961#[derive(Clone, Copy, Default)]
4962pub struct IterableOpDevGetDumpReply<'a> {
4963    buf: &'a [u8],
4964    pos: usize,
4965    orig_loc: usize,
4966}
4967impl<'a> IterableOpDevGetDumpReply<'a> {
4968    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4969        Self {
4970            buf,
4971            pos: 0,
4972            orig_loc,
4973        }
4974    }
4975    pub fn get_buf(&self) -> &'a [u8] {
4976        self.buf
4977    }
4978}
4979impl<'a> Iterator for IterableOpDevGetDumpReply<'a> {
4980    type Item = Result<OpDevGetDumpReply, ErrorContext>;
4981    fn next(&mut self) -> Option<Self::Item> {
4982        if self.buf.len() == self.pos {
4983            return None;
4984        }
4985        let pos = self.pos;
4986        let mut r#type = None;
4987        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
4988            r#type = Some(header.r#type);
4989            let res = match header.r#type {
4990                1u16 => OpDevGetDumpReply::Ifindex({
4991                    let res = parse_u32(next);
4992                    let Some(val) = res else { break };
4993                    val
4994                }),
4995                3u16 => OpDevGetDumpReply::XdpFeatures({
4996                    let res = parse_u64(next);
4997                    let Some(val) = res else { break };
4998                    val
4999                }),
5000                4u16 => OpDevGetDumpReply::XdpZcMaxSegs({
5001                    let res = parse_u32(next);
5002                    let Some(val) = res else { break };
5003                    val
5004                }),
5005                5u16 => OpDevGetDumpReply::XdpRxMetadataFeatures({
5006                    let res = parse_u64(next);
5007                    let Some(val) = res else { break };
5008                    val
5009                }),
5010                6u16 => OpDevGetDumpReply::XskFeatures({
5011                    let res = parse_u64(next);
5012                    let Some(val) = res else { break };
5013                    val
5014                }),
5015                n => {
5016                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
5017                        break;
5018                    } else {
5019                        continue;
5020                    }
5021                }
5022            };
5023            return Some(Ok(res));
5024        }
5025        Some(Err(ErrorContext::new(
5026            "OpDevGetDumpReply",
5027            r#type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5028            self.orig_loc,
5029            self.buf.as_ptr().wrapping_add(pos) as usize,
5030        )))
5031    }
5032}
5033impl std::fmt::Debug for IterableOpDevGetDumpReply<'_> {
5034    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5035        let mut fmt = f.debug_struct("OpDevGetDumpReply");
5036        for attr in self.clone() {
5037            let attr = match attr {
5038                Ok(a) => a,
5039                Err(err) => {
5040                    fmt.finish()?;
5041                    f.write_str("Err(")?;
5042                    err.fmt(f)?;
5043                    return f.write_str(")");
5044                }
5045            };
5046            match attr {
5047                OpDevGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
5048                OpDevGetDumpReply::XdpFeatures(val) => {
5049                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5050                }
5051                OpDevGetDumpReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5052                OpDevGetDumpReply::XdpRxMetadataFeatures(val) => fmt.field(
5053                    "XdpRxMetadataFeatures",
5054                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
5055                ),
5056                OpDevGetDumpReply::XskFeatures(val) => fmt.field(
5057                    "XskFeatures",
5058                    &FormatFlags(val.into(), XskFlags::from_value),
5059                ),
5060            };
5061        }
5062        fmt.finish()
5063    }
5064}
5065impl IterableOpDevGetDumpReply<'_> {
5066    pub fn lookup_attr(
5067        &self,
5068        offset: usize,
5069        missing_type: Option<u16>,
5070    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5071        let mut stack = Vec::new();
5072        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5073        if cur == offset + PushBuiltinNfgenmsg::len() {
5074            stack.push(("OpDevGetDumpReply", offset));
5075            return (
5076                stack,
5077                missing_type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5078            );
5079        }
5080        if cur > offset || cur + self.buf.len() < offset {
5081            return (stack, None);
5082        }
5083        let mut attrs = self.clone();
5084        let mut last_off = cur + attrs.pos;
5085        while let Some(attr) = attrs.next() {
5086            let Ok(attr) = attr else { break };
5087            match attr {
5088                OpDevGetDumpReply::Ifindex(val) => {
5089                    if last_off == offset {
5090                        stack.push(("Ifindex", last_off));
5091                        break;
5092                    }
5093                }
5094                OpDevGetDumpReply::XdpFeatures(val) => {
5095                    if last_off == offset {
5096                        stack.push(("XdpFeatures", last_off));
5097                        break;
5098                    }
5099                }
5100                OpDevGetDumpReply::XdpZcMaxSegs(val) => {
5101                    if last_off == offset {
5102                        stack.push(("XdpZcMaxSegs", last_off));
5103                        break;
5104                    }
5105                }
5106                OpDevGetDumpReply::XdpRxMetadataFeatures(val) => {
5107                    if last_off == offset {
5108                        stack.push(("XdpRxMetadataFeatures", last_off));
5109                        break;
5110                    }
5111                }
5112                OpDevGetDumpReply::XskFeatures(val) => {
5113                    if last_off == offset {
5114                        stack.push(("XskFeatures", last_off));
5115                        break;
5116                    }
5117                }
5118                _ => {}
5119            };
5120            last_off = cur + attrs.pos;
5121        }
5122        if !stack.is_empty() {
5123            stack.push(("OpDevGetDumpReply", cur));
5124        }
5125        (stack, None)
5126    }
5127}
5128#[derive(Debug)]
5129pub struct RequestOpDevGetDumpRequest<'r> {
5130    request: Request<'r>,
5131}
5132impl<'r> RequestOpDevGetDumpRequest<'r> {
5133    pub fn new(mut request: Request<'r>) -> Self {
5134        PushOpDevGetDumpRequest::write_header(&mut request.buf_mut());
5135        Self {
5136            request: request.set_dump(),
5137        }
5138    }
5139    pub fn encode(&mut self) -> PushOpDevGetDumpRequest<&mut Vec<u8>> {
5140        PushOpDevGetDumpRequest::new_without_header(self.request.buf_mut())
5141    }
5142    pub fn into_encoder(self) -> PushOpDevGetDumpRequest<RequestBuf<'r>> {
5143        PushOpDevGetDumpRequest::new_without_header(self.request.buf)
5144    }
5145}
5146impl NetlinkRequest for RequestOpDevGetDumpRequest<'_> {
5147    type ReplyType<'buf> = IterableOpDevGetDumpReply<'buf>;
5148    fn protocol(&self) -> Protocol {
5149        Protocol::Generic("netdev".as_bytes())
5150    }
5151    fn flags(&self) -> u16 {
5152        self.request.flags
5153    }
5154    fn payload(&self) -> &[u8] {
5155        self.request.buf()
5156    }
5157    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5158        OpDevGetDumpReply::new(buf)
5159    }
5160    fn lookup(
5161        buf: &[u8],
5162        offset: usize,
5163        missing_type: Option<u16>,
5164    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5165        OpDevGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
5166    }
5167}
5168#[doc = "Get / dump information about a netdev."]
5169pub struct PushOpDevGetDoRequest<Prev: Rec> {
5170    pub(crate) prev: Option<Prev>,
5171    pub(crate) header_offset: Option<usize>,
5172}
5173impl<Prev: Rec> Rec for PushOpDevGetDoRequest<Prev> {
5174    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5175        self.prev.as_mut().unwrap().as_rec_mut()
5176    }
5177}
5178impl<Prev: Rec> PushOpDevGetDoRequest<Prev> {
5179    pub fn new(mut prev: Prev) -> Self {
5180        Self::write_header(&mut prev);
5181        Self::new_without_header(prev)
5182    }
5183    fn new_without_header(prev: Prev) -> Self {
5184        Self {
5185            prev: Some(prev),
5186            header_offset: None,
5187        }
5188    }
5189    fn write_header(prev: &mut Prev) {
5190        let mut header = PushBuiltinNfgenmsg::new();
5191        header.set_cmd(1u8);
5192        header.set_version(1u8);
5193        prev.as_rec_mut().extend(header.as_slice());
5194    }
5195    pub fn end_nested(mut self) -> Prev {
5196        let mut prev = self.prev.take().unwrap();
5197        if let Some(header_offset) = &self.header_offset {
5198            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5199        }
5200        prev
5201    }
5202    #[doc = "netdev ifindex"]
5203    pub fn push_ifindex(mut self, value: u32) -> Self {
5204        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5205        self.as_rec_mut().extend(value.to_ne_bytes());
5206        self
5207    }
5208}
5209impl<Prev: Rec> Drop for PushOpDevGetDoRequest<Prev> {
5210    fn drop(&mut self) {
5211        if let Some(prev) = &mut self.prev {
5212            if let Some(header_offset) = &self.header_offset {
5213                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5214            }
5215        }
5216    }
5217}
5218#[doc = "Get / dump information about a netdev."]
5219#[derive(Clone)]
5220pub enum OpDevGetDoRequest {
5221    #[doc = "netdev ifindex"]
5222    Ifindex(u32),
5223}
5224impl<'a> IterableOpDevGetDoRequest<'a> {
5225    #[doc = "netdev ifindex"]
5226    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5227        let mut iter = self.clone();
5228        iter.pos = 0;
5229        for attr in iter {
5230            if let OpDevGetDoRequest::Ifindex(val) = attr? {
5231                return Ok(val);
5232            }
5233        }
5234        Err(ErrorContext::new_missing(
5235            "OpDevGetDoRequest",
5236            "Ifindex",
5237            self.orig_loc,
5238            self.buf.as_ptr() as usize,
5239        ))
5240    }
5241}
5242impl OpDevGetDoRequest {
5243    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoRequest<'a> {
5244        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5245        IterableOpDevGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
5246    }
5247    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5248        Dev::attr_from_type(r#type)
5249    }
5250}
5251#[derive(Clone, Copy, Default)]
5252pub struct IterableOpDevGetDoRequest<'a> {
5253    buf: &'a [u8],
5254    pos: usize,
5255    orig_loc: usize,
5256}
5257impl<'a> IterableOpDevGetDoRequest<'a> {
5258    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5259        Self {
5260            buf,
5261            pos: 0,
5262            orig_loc,
5263        }
5264    }
5265    pub fn get_buf(&self) -> &'a [u8] {
5266        self.buf
5267    }
5268}
5269impl<'a> Iterator for IterableOpDevGetDoRequest<'a> {
5270    type Item = Result<OpDevGetDoRequest, ErrorContext>;
5271    fn next(&mut self) -> Option<Self::Item> {
5272        if self.buf.len() == self.pos {
5273            return None;
5274        }
5275        let pos = self.pos;
5276        let mut r#type = None;
5277        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5278            r#type = Some(header.r#type);
5279            let res = match header.r#type {
5280                1u16 => OpDevGetDoRequest::Ifindex({
5281                    let res = parse_u32(next);
5282                    let Some(val) = res else { break };
5283                    val
5284                }),
5285                n => {
5286                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
5287                        break;
5288                    } else {
5289                        continue;
5290                    }
5291                }
5292            };
5293            return Some(Ok(res));
5294        }
5295        Some(Err(ErrorContext::new(
5296            "OpDevGetDoRequest",
5297            r#type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5298            self.orig_loc,
5299            self.buf.as_ptr().wrapping_add(pos) as usize,
5300        )))
5301    }
5302}
5303impl std::fmt::Debug for IterableOpDevGetDoRequest<'_> {
5304    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5305        let mut fmt = f.debug_struct("OpDevGetDoRequest");
5306        for attr in self.clone() {
5307            let attr = match attr {
5308                Ok(a) => a,
5309                Err(err) => {
5310                    fmt.finish()?;
5311                    f.write_str("Err(")?;
5312                    err.fmt(f)?;
5313                    return f.write_str(")");
5314                }
5315            };
5316            match attr {
5317                OpDevGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
5318            };
5319        }
5320        fmt.finish()
5321    }
5322}
5323impl IterableOpDevGetDoRequest<'_> {
5324    pub fn lookup_attr(
5325        &self,
5326        offset: usize,
5327        missing_type: Option<u16>,
5328    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5329        let mut stack = Vec::new();
5330        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5331        if cur == offset + PushBuiltinNfgenmsg::len() {
5332            stack.push(("OpDevGetDoRequest", offset));
5333            return (
5334                stack,
5335                missing_type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5336            );
5337        }
5338        if cur > offset || cur + self.buf.len() < offset {
5339            return (stack, None);
5340        }
5341        let mut attrs = self.clone();
5342        let mut last_off = cur + attrs.pos;
5343        while let Some(attr) = attrs.next() {
5344            let Ok(attr) = attr else { break };
5345            match attr {
5346                OpDevGetDoRequest::Ifindex(val) => {
5347                    if last_off == offset {
5348                        stack.push(("Ifindex", last_off));
5349                        break;
5350                    }
5351                }
5352                _ => {}
5353            };
5354            last_off = cur + attrs.pos;
5355        }
5356        if !stack.is_empty() {
5357            stack.push(("OpDevGetDoRequest", cur));
5358        }
5359        (stack, None)
5360    }
5361}
5362#[doc = "Get / dump information about a netdev."]
5363pub struct PushOpDevGetDoReply<Prev: Rec> {
5364    pub(crate) prev: Option<Prev>,
5365    pub(crate) header_offset: Option<usize>,
5366}
5367impl<Prev: Rec> Rec for PushOpDevGetDoReply<Prev> {
5368    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5369        self.prev.as_mut().unwrap().as_rec_mut()
5370    }
5371}
5372impl<Prev: Rec> PushOpDevGetDoReply<Prev> {
5373    pub fn new(mut prev: Prev) -> Self {
5374        Self::write_header(&mut prev);
5375        Self::new_without_header(prev)
5376    }
5377    fn new_without_header(prev: Prev) -> Self {
5378        Self {
5379            prev: Some(prev),
5380            header_offset: None,
5381        }
5382    }
5383    fn write_header(prev: &mut Prev) {
5384        let mut header = PushBuiltinNfgenmsg::new();
5385        header.set_cmd(1u8);
5386        header.set_version(1u8);
5387        prev.as_rec_mut().extend(header.as_slice());
5388    }
5389    pub fn end_nested(mut self) -> Prev {
5390        let mut prev = self.prev.take().unwrap();
5391        if let Some(header_offset) = &self.header_offset {
5392            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5393        }
5394        prev
5395    }
5396    #[doc = "netdev ifindex"]
5397    pub fn push_ifindex(mut self, value: u32) -> Self {
5398        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5399        self.as_rec_mut().extend(value.to_ne_bytes());
5400        self
5401    }
5402    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5403    pub fn push_xdp_features(mut self, value: u64) -> Self {
5404        push_header(self.as_rec_mut(), 3u16, 8 as u16);
5405        self.as_rec_mut().extend(value.to_ne_bytes());
5406        self
5407    }
5408    #[doc = "max fragment count supported by ZC driver"]
5409    pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
5410        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5411        self.as_rec_mut().extend(value.to_ne_bytes());
5412        self
5413    }
5414    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5415    pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
5416        push_header(self.as_rec_mut(), 5u16, 8 as u16);
5417        self.as_rec_mut().extend(value.to_ne_bytes());
5418        self
5419    }
5420    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5421    pub fn push_xsk_features(mut self, value: u64) -> Self {
5422        push_header(self.as_rec_mut(), 6u16, 8 as u16);
5423        self.as_rec_mut().extend(value.to_ne_bytes());
5424        self
5425    }
5426}
5427impl<Prev: Rec> Drop for PushOpDevGetDoReply<Prev> {
5428    fn drop(&mut self) {
5429        if let Some(prev) = &mut self.prev {
5430            if let Some(header_offset) = &self.header_offset {
5431                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5432            }
5433        }
5434    }
5435}
5436#[doc = "Get / dump information about a netdev."]
5437#[derive(Clone)]
5438pub enum OpDevGetDoReply {
5439    #[doc = "netdev ifindex"]
5440    Ifindex(u32),
5441    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5442    XdpFeatures(u64),
5443    #[doc = "max fragment count supported by ZC driver"]
5444    XdpZcMaxSegs(u32),
5445    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5446    XdpRxMetadataFeatures(u64),
5447    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5448    XskFeatures(u64),
5449}
5450impl<'a> IterableOpDevGetDoReply<'a> {
5451    #[doc = "netdev ifindex"]
5452    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5453        let mut iter = self.clone();
5454        iter.pos = 0;
5455        for attr in iter {
5456            if let OpDevGetDoReply::Ifindex(val) = attr? {
5457                return Ok(val);
5458            }
5459        }
5460        Err(ErrorContext::new_missing(
5461            "OpDevGetDoReply",
5462            "Ifindex",
5463            self.orig_loc,
5464            self.buf.as_ptr() as usize,
5465        ))
5466    }
5467    #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5468    pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
5469        let mut iter = self.clone();
5470        iter.pos = 0;
5471        for attr in iter {
5472            if let OpDevGetDoReply::XdpFeatures(val) = attr? {
5473                return Ok(val);
5474            }
5475        }
5476        Err(ErrorContext::new_missing(
5477            "OpDevGetDoReply",
5478            "XdpFeatures",
5479            self.orig_loc,
5480            self.buf.as_ptr() as usize,
5481        ))
5482    }
5483    #[doc = "max fragment count supported by ZC driver"]
5484    pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
5485        let mut iter = self.clone();
5486        iter.pos = 0;
5487        for attr in iter {
5488            if let OpDevGetDoReply::XdpZcMaxSegs(val) = attr? {
5489                return Ok(val);
5490            }
5491        }
5492        Err(ErrorContext::new_missing(
5493            "OpDevGetDoReply",
5494            "XdpZcMaxSegs",
5495            self.orig_loc,
5496            self.buf.as_ptr() as usize,
5497        ))
5498    }
5499    #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5500    pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
5501        let mut iter = self.clone();
5502        iter.pos = 0;
5503        for attr in iter {
5504            if let OpDevGetDoReply::XdpRxMetadataFeatures(val) = attr? {
5505                return Ok(val);
5506            }
5507        }
5508        Err(ErrorContext::new_missing(
5509            "OpDevGetDoReply",
5510            "XdpRxMetadataFeatures",
5511            self.orig_loc,
5512            self.buf.as_ptr() as usize,
5513        ))
5514    }
5515    #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5516    pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
5517        let mut iter = self.clone();
5518        iter.pos = 0;
5519        for attr in iter {
5520            if let OpDevGetDoReply::XskFeatures(val) = attr? {
5521                return Ok(val);
5522            }
5523        }
5524        Err(ErrorContext::new_missing(
5525            "OpDevGetDoReply",
5526            "XskFeatures",
5527            self.orig_loc,
5528            self.buf.as_ptr() as usize,
5529        ))
5530    }
5531}
5532impl OpDevGetDoReply {
5533    pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoReply<'a> {
5534        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5535        IterableOpDevGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
5536    }
5537    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5538        Dev::attr_from_type(r#type)
5539    }
5540}
5541#[derive(Clone, Copy, Default)]
5542pub struct IterableOpDevGetDoReply<'a> {
5543    buf: &'a [u8],
5544    pos: usize,
5545    orig_loc: usize,
5546}
5547impl<'a> IterableOpDevGetDoReply<'a> {
5548    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5549        Self {
5550            buf,
5551            pos: 0,
5552            orig_loc,
5553        }
5554    }
5555    pub fn get_buf(&self) -> &'a [u8] {
5556        self.buf
5557    }
5558}
5559impl<'a> Iterator for IterableOpDevGetDoReply<'a> {
5560    type Item = Result<OpDevGetDoReply, ErrorContext>;
5561    fn next(&mut self) -> Option<Self::Item> {
5562        if self.buf.len() == self.pos {
5563            return None;
5564        }
5565        let pos = self.pos;
5566        let mut r#type = None;
5567        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5568            r#type = Some(header.r#type);
5569            let res = match header.r#type {
5570                1u16 => OpDevGetDoReply::Ifindex({
5571                    let res = parse_u32(next);
5572                    let Some(val) = res else { break };
5573                    val
5574                }),
5575                3u16 => OpDevGetDoReply::XdpFeatures({
5576                    let res = parse_u64(next);
5577                    let Some(val) = res else { break };
5578                    val
5579                }),
5580                4u16 => OpDevGetDoReply::XdpZcMaxSegs({
5581                    let res = parse_u32(next);
5582                    let Some(val) = res else { break };
5583                    val
5584                }),
5585                5u16 => OpDevGetDoReply::XdpRxMetadataFeatures({
5586                    let res = parse_u64(next);
5587                    let Some(val) = res else { break };
5588                    val
5589                }),
5590                6u16 => OpDevGetDoReply::XskFeatures({
5591                    let res = parse_u64(next);
5592                    let Some(val) = res else { break };
5593                    val
5594                }),
5595                n => {
5596                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
5597                        break;
5598                    } else {
5599                        continue;
5600                    }
5601                }
5602            };
5603            return Some(Ok(res));
5604        }
5605        Some(Err(ErrorContext::new(
5606            "OpDevGetDoReply",
5607            r#type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5608            self.orig_loc,
5609            self.buf.as_ptr().wrapping_add(pos) as usize,
5610        )))
5611    }
5612}
5613impl std::fmt::Debug for IterableOpDevGetDoReply<'_> {
5614    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5615        let mut fmt = f.debug_struct("OpDevGetDoReply");
5616        for attr in self.clone() {
5617            let attr = match attr {
5618                Ok(a) => a,
5619                Err(err) => {
5620                    fmt.finish()?;
5621                    f.write_str("Err(")?;
5622                    err.fmt(f)?;
5623                    return f.write_str(")");
5624                }
5625            };
5626            match attr {
5627                OpDevGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
5628                OpDevGetDoReply::XdpFeatures(val) => {
5629                    fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5630                }
5631                OpDevGetDoReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5632                OpDevGetDoReply::XdpRxMetadataFeatures(val) => fmt.field(
5633                    "XdpRxMetadataFeatures",
5634                    &FormatFlags(val.into(), XdpRxMetadata::from_value),
5635                ),
5636                OpDevGetDoReply::XskFeatures(val) => fmt.field(
5637                    "XskFeatures",
5638                    &FormatFlags(val.into(), XskFlags::from_value),
5639                ),
5640            };
5641        }
5642        fmt.finish()
5643    }
5644}
5645impl IterableOpDevGetDoReply<'_> {
5646    pub fn lookup_attr(
5647        &self,
5648        offset: usize,
5649        missing_type: Option<u16>,
5650    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5651        let mut stack = Vec::new();
5652        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5653        if cur == offset + PushBuiltinNfgenmsg::len() {
5654            stack.push(("OpDevGetDoReply", offset));
5655            return (
5656                stack,
5657                missing_type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5658            );
5659        }
5660        if cur > offset || cur + self.buf.len() < offset {
5661            return (stack, None);
5662        }
5663        let mut attrs = self.clone();
5664        let mut last_off = cur + attrs.pos;
5665        while let Some(attr) = attrs.next() {
5666            let Ok(attr) = attr else { break };
5667            match attr {
5668                OpDevGetDoReply::Ifindex(val) => {
5669                    if last_off == offset {
5670                        stack.push(("Ifindex", last_off));
5671                        break;
5672                    }
5673                }
5674                OpDevGetDoReply::XdpFeatures(val) => {
5675                    if last_off == offset {
5676                        stack.push(("XdpFeatures", last_off));
5677                        break;
5678                    }
5679                }
5680                OpDevGetDoReply::XdpZcMaxSegs(val) => {
5681                    if last_off == offset {
5682                        stack.push(("XdpZcMaxSegs", last_off));
5683                        break;
5684                    }
5685                }
5686                OpDevGetDoReply::XdpRxMetadataFeatures(val) => {
5687                    if last_off == offset {
5688                        stack.push(("XdpRxMetadataFeatures", last_off));
5689                        break;
5690                    }
5691                }
5692                OpDevGetDoReply::XskFeatures(val) => {
5693                    if last_off == offset {
5694                        stack.push(("XskFeatures", last_off));
5695                        break;
5696                    }
5697                }
5698                _ => {}
5699            };
5700            last_off = cur + attrs.pos;
5701        }
5702        if !stack.is_empty() {
5703            stack.push(("OpDevGetDoReply", cur));
5704        }
5705        (stack, None)
5706    }
5707}
5708#[derive(Debug)]
5709pub struct RequestOpDevGetDoRequest<'r> {
5710    request: Request<'r>,
5711}
5712impl<'r> RequestOpDevGetDoRequest<'r> {
5713    pub fn new(mut request: Request<'r>) -> Self {
5714        PushOpDevGetDoRequest::write_header(&mut request.buf_mut());
5715        Self { request: request }
5716    }
5717    pub fn encode(&mut self) -> PushOpDevGetDoRequest<&mut Vec<u8>> {
5718        PushOpDevGetDoRequest::new_without_header(self.request.buf_mut())
5719    }
5720    pub fn into_encoder(self) -> PushOpDevGetDoRequest<RequestBuf<'r>> {
5721        PushOpDevGetDoRequest::new_without_header(self.request.buf)
5722    }
5723}
5724impl NetlinkRequest for RequestOpDevGetDoRequest<'_> {
5725    type ReplyType<'buf> = IterableOpDevGetDoReply<'buf>;
5726    fn protocol(&self) -> Protocol {
5727        Protocol::Generic("netdev".as_bytes())
5728    }
5729    fn flags(&self) -> u16 {
5730        self.request.flags
5731    }
5732    fn payload(&self) -> &[u8] {
5733        self.request.buf()
5734    }
5735    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5736        OpDevGetDoReply::new(buf)
5737    }
5738    fn lookup(
5739        buf: &[u8],
5740        offset: usize,
5741        missing_type: Option<u16>,
5742    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5743        OpDevGetDoRequest::new(buf).lookup_attr(offset, missing_type)
5744    }
5745}
5746#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5747pub struct PushOpPagePoolGetDumpRequest<Prev: Rec> {
5748    pub(crate) prev: Option<Prev>,
5749    pub(crate) header_offset: Option<usize>,
5750}
5751impl<Prev: Rec> Rec for PushOpPagePoolGetDumpRequest<Prev> {
5752    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5753        self.prev.as_mut().unwrap().as_rec_mut()
5754    }
5755}
5756impl<Prev: Rec> PushOpPagePoolGetDumpRequest<Prev> {
5757    pub fn new(mut prev: Prev) -> Self {
5758        Self::write_header(&mut prev);
5759        Self::new_without_header(prev)
5760    }
5761    fn new_without_header(prev: Prev) -> Self {
5762        Self {
5763            prev: Some(prev),
5764            header_offset: None,
5765        }
5766    }
5767    fn write_header(prev: &mut Prev) {
5768        let mut header = PushBuiltinNfgenmsg::new();
5769        header.set_cmd(5u8);
5770        header.set_version(1u8);
5771        prev.as_rec_mut().extend(header.as_slice());
5772    }
5773    pub fn end_nested(mut self) -> Prev {
5774        let mut prev = self.prev.take().unwrap();
5775        if let Some(header_offset) = &self.header_offset {
5776            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5777        }
5778        prev
5779    }
5780}
5781impl<Prev: Rec> Drop for PushOpPagePoolGetDumpRequest<Prev> {
5782    fn drop(&mut self) {
5783        if let Some(prev) = &mut self.prev {
5784            if let Some(header_offset) = &self.header_offset {
5785                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5786            }
5787        }
5788    }
5789}
5790#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5791#[derive(Clone)]
5792pub enum OpPagePoolGetDumpRequest {}
5793impl<'a> IterableOpPagePoolGetDumpRequest<'a> {}
5794impl OpPagePoolGetDumpRequest {
5795    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpRequest<'a> {
5796        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5797        IterableOpPagePoolGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
5798    }
5799    fn attr_from_type(r#type: u16) -> Option<&'static str> {
5800        PagePool::attr_from_type(r#type)
5801    }
5802}
5803#[derive(Clone, Copy, Default)]
5804pub struct IterableOpPagePoolGetDumpRequest<'a> {
5805    buf: &'a [u8],
5806    pos: usize,
5807    orig_loc: usize,
5808}
5809impl<'a> IterableOpPagePoolGetDumpRequest<'a> {
5810    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5811        Self {
5812            buf,
5813            pos: 0,
5814            orig_loc,
5815        }
5816    }
5817    pub fn get_buf(&self) -> &'a [u8] {
5818        self.buf
5819    }
5820}
5821impl<'a> Iterator for IterableOpPagePoolGetDumpRequest<'a> {
5822    type Item = Result<OpPagePoolGetDumpRequest, ErrorContext>;
5823    fn next(&mut self) -> Option<Self::Item> {
5824        if self.buf.len() == self.pos {
5825            return None;
5826        }
5827        let pos = self.pos;
5828        let mut r#type = None;
5829        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5830            r#type = Some(header.r#type);
5831            let res = match header.r#type {
5832                n => {
5833                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
5834                        break;
5835                    } else {
5836                        continue;
5837                    }
5838                }
5839            };
5840            return Some(Ok(res));
5841        }
5842        Some(Err(ErrorContext::new(
5843            "OpPagePoolGetDumpRequest",
5844            r#type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5845            self.orig_loc,
5846            self.buf.as_ptr().wrapping_add(pos) as usize,
5847        )))
5848    }
5849}
5850impl std::fmt::Debug for IterableOpPagePoolGetDumpRequest<'_> {
5851    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5852        let mut fmt = f.debug_struct("OpPagePoolGetDumpRequest");
5853        for attr in self.clone() {
5854            let attr = match attr {
5855                Ok(a) => a,
5856                Err(err) => {
5857                    fmt.finish()?;
5858                    f.write_str("Err(")?;
5859                    err.fmt(f)?;
5860                    return f.write_str(")");
5861                }
5862            };
5863            match attr {};
5864        }
5865        fmt.finish()
5866    }
5867}
5868impl IterableOpPagePoolGetDumpRequest<'_> {
5869    pub fn lookup_attr(
5870        &self,
5871        offset: usize,
5872        missing_type: Option<u16>,
5873    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5874        let mut stack = Vec::new();
5875        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5876        if cur == offset + PushBuiltinNfgenmsg::len() {
5877            stack.push(("OpPagePoolGetDumpRequest", offset));
5878            return (
5879                stack,
5880                missing_type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5881            );
5882        }
5883        (stack, None)
5884    }
5885}
5886#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5887pub struct PushOpPagePoolGetDumpReply<Prev: Rec> {
5888    pub(crate) prev: Option<Prev>,
5889    pub(crate) header_offset: Option<usize>,
5890}
5891impl<Prev: Rec> Rec for PushOpPagePoolGetDumpReply<Prev> {
5892    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5893        self.prev.as_mut().unwrap().as_rec_mut()
5894    }
5895}
5896impl<Prev: Rec> PushOpPagePoolGetDumpReply<Prev> {
5897    pub fn new(mut prev: Prev) -> Self {
5898        Self::write_header(&mut prev);
5899        Self::new_without_header(prev)
5900    }
5901    fn new_without_header(prev: Prev) -> Self {
5902        Self {
5903            prev: Some(prev),
5904            header_offset: None,
5905        }
5906    }
5907    fn write_header(prev: &mut Prev) {
5908        let mut header = PushBuiltinNfgenmsg::new();
5909        header.set_cmd(5u8);
5910        header.set_version(1u8);
5911        prev.as_rec_mut().extend(header.as_slice());
5912    }
5913    pub fn end_nested(mut self) -> Prev {
5914        let mut prev = self.prev.take().unwrap();
5915        if let Some(header_offset) = &self.header_offset {
5916            finalize_nested_header(prev.as_rec_mut(), *header_offset);
5917        }
5918        prev
5919    }
5920    #[doc = "Unique ID of a Page Pool instance."]
5921    pub fn push_id(mut self, value: u32) -> Self {
5922        push_header(self.as_rec_mut(), 1u16, 4 as u16);
5923        self.as_rec_mut().extend(value.to_ne_bytes());
5924        self
5925    }
5926    #[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"]
5927    pub fn push_ifindex(mut self, value: u32) -> Self {
5928        push_header(self.as_rec_mut(), 2u16, 4 as u16);
5929        self.as_rec_mut().extend(value.to_ne_bytes());
5930        self
5931    }
5932    #[doc = "Id of NAPI using this Page Pool instance."]
5933    pub fn push_napi_id(mut self, value: u32) -> Self {
5934        push_header(self.as_rec_mut(), 3u16, 4 as u16);
5935        self.as_rec_mut().extend(value.to_ne_bytes());
5936        self
5937    }
5938    #[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"]
5939    pub fn push_inflight(mut self, value: u32) -> Self {
5940        push_header(self.as_rec_mut(), 4u16, 4 as u16);
5941        self.as_rec_mut().extend(value.to_ne_bytes());
5942        self
5943    }
5944    #[doc = "Amount of memory held by inflight pages.\n"]
5945    pub fn push_inflight_mem(mut self, value: u32) -> Self {
5946        push_header(self.as_rec_mut(), 5u16, 4 as u16);
5947        self.as_rec_mut().extend(value.to_ne_bytes());
5948        self
5949    }
5950    #[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"]
5951    pub fn push_detach_time(mut self, value: u32) -> Self {
5952        push_header(self.as_rec_mut(), 6u16, 4 as u16);
5953        self.as_rec_mut().extend(value.to_ne_bytes());
5954        self
5955    }
5956    #[doc = "ID of the dmabuf this page-pool is attached to."]
5957    pub fn push_dmabuf(mut self, value: u32) -> Self {
5958        push_header(self.as_rec_mut(), 7u16, 4 as u16);
5959        self.as_rec_mut().extend(value.to_ne_bytes());
5960        self
5961    }
5962    #[doc = "io-uring memory provider information."]
5963    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
5964        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
5965        PushIoUringProviderInfo {
5966            prev: Some(self),
5967            header_offset: Some(header_offset),
5968        }
5969    }
5970}
5971impl<Prev: Rec> Drop for PushOpPagePoolGetDumpReply<Prev> {
5972    fn drop(&mut self) {
5973        if let Some(prev) = &mut self.prev {
5974            if let Some(header_offset) = &self.header_offset {
5975                finalize_nested_header(prev.as_rec_mut(), *header_offset);
5976            }
5977        }
5978    }
5979}
5980#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5981#[derive(Clone)]
5982pub enum OpPagePoolGetDumpReply<'a> {
5983    #[doc = "Unique ID of a Page Pool instance."]
5984    Id(u32),
5985    #[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"]
5986    Ifindex(u32),
5987    #[doc = "Id of NAPI using this Page Pool instance."]
5988    NapiId(u32),
5989    #[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"]
5990    Inflight(u32),
5991    #[doc = "Amount of memory held by inflight pages.\n"]
5992    InflightMem(u32),
5993    #[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"]
5994    DetachTime(u32),
5995    #[doc = "ID of the dmabuf this page-pool is attached to."]
5996    Dmabuf(u32),
5997    #[doc = "io-uring memory provider information."]
5998    IoUring(IterableIoUringProviderInfo<'a>),
5999}
6000impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6001    #[doc = "Unique ID of a Page Pool instance."]
6002    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6003        let mut iter = self.clone();
6004        iter.pos = 0;
6005        for attr in iter {
6006            if let OpPagePoolGetDumpReply::Id(val) = attr? {
6007                return Ok(val);
6008            }
6009        }
6010        Err(ErrorContext::new_missing(
6011            "OpPagePoolGetDumpReply",
6012            "Id",
6013            self.orig_loc,
6014            self.buf.as_ptr() as usize,
6015        ))
6016    }
6017    #[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"]
6018    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6019        let mut iter = self.clone();
6020        iter.pos = 0;
6021        for attr in iter {
6022            if let OpPagePoolGetDumpReply::Ifindex(val) = attr? {
6023                return Ok(val);
6024            }
6025        }
6026        Err(ErrorContext::new_missing(
6027            "OpPagePoolGetDumpReply",
6028            "Ifindex",
6029            self.orig_loc,
6030            self.buf.as_ptr() as usize,
6031        ))
6032    }
6033    #[doc = "Id of NAPI using this Page Pool instance."]
6034    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6035        let mut iter = self.clone();
6036        iter.pos = 0;
6037        for attr in iter {
6038            if let OpPagePoolGetDumpReply::NapiId(val) = attr? {
6039                return Ok(val);
6040            }
6041        }
6042        Err(ErrorContext::new_missing(
6043            "OpPagePoolGetDumpReply",
6044            "NapiId",
6045            self.orig_loc,
6046            self.buf.as_ptr() as usize,
6047        ))
6048    }
6049    #[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"]
6050    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6051        let mut iter = self.clone();
6052        iter.pos = 0;
6053        for attr in iter {
6054            if let OpPagePoolGetDumpReply::Inflight(val) = attr? {
6055                return Ok(val);
6056            }
6057        }
6058        Err(ErrorContext::new_missing(
6059            "OpPagePoolGetDumpReply",
6060            "Inflight",
6061            self.orig_loc,
6062            self.buf.as_ptr() as usize,
6063        ))
6064    }
6065    #[doc = "Amount of memory held by inflight pages.\n"]
6066    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6067        let mut iter = self.clone();
6068        iter.pos = 0;
6069        for attr in iter {
6070            if let OpPagePoolGetDumpReply::InflightMem(val) = attr? {
6071                return Ok(val);
6072            }
6073        }
6074        Err(ErrorContext::new_missing(
6075            "OpPagePoolGetDumpReply",
6076            "InflightMem",
6077            self.orig_loc,
6078            self.buf.as_ptr() as usize,
6079        ))
6080    }
6081    #[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"]
6082    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6083        let mut iter = self.clone();
6084        iter.pos = 0;
6085        for attr in iter {
6086            if let OpPagePoolGetDumpReply::DetachTime(val) = attr? {
6087                return Ok(val);
6088            }
6089        }
6090        Err(ErrorContext::new_missing(
6091            "OpPagePoolGetDumpReply",
6092            "DetachTime",
6093            self.orig_loc,
6094            self.buf.as_ptr() as usize,
6095        ))
6096    }
6097    #[doc = "ID of the dmabuf this page-pool is attached to."]
6098    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6099        let mut iter = self.clone();
6100        iter.pos = 0;
6101        for attr in iter {
6102            if let OpPagePoolGetDumpReply::Dmabuf(val) = attr? {
6103                return Ok(val);
6104            }
6105        }
6106        Err(ErrorContext::new_missing(
6107            "OpPagePoolGetDumpReply",
6108            "Dmabuf",
6109            self.orig_loc,
6110            self.buf.as_ptr() as usize,
6111        ))
6112    }
6113    #[doc = "io-uring memory provider information."]
6114    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6115        let mut iter = self.clone();
6116        iter.pos = 0;
6117        for attr in iter {
6118            if let OpPagePoolGetDumpReply::IoUring(val) = attr? {
6119                return Ok(val);
6120            }
6121        }
6122        Err(ErrorContext::new_missing(
6123            "OpPagePoolGetDumpReply",
6124            "IoUring",
6125            self.orig_loc,
6126            self.buf.as_ptr() as usize,
6127        ))
6128    }
6129}
6130impl OpPagePoolGetDumpReply<'_> {
6131    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpReply<'a> {
6132        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6133        IterableOpPagePoolGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
6134    }
6135    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6136        PagePool::attr_from_type(r#type)
6137    }
6138}
6139#[derive(Clone, Copy, Default)]
6140pub struct IterableOpPagePoolGetDumpReply<'a> {
6141    buf: &'a [u8],
6142    pos: usize,
6143    orig_loc: usize,
6144}
6145impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6146    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6147        Self {
6148            buf,
6149            pos: 0,
6150            orig_loc,
6151        }
6152    }
6153    pub fn get_buf(&self) -> &'a [u8] {
6154        self.buf
6155    }
6156}
6157impl<'a> Iterator for IterableOpPagePoolGetDumpReply<'a> {
6158    type Item = Result<OpPagePoolGetDumpReply<'a>, ErrorContext>;
6159    fn next(&mut self) -> Option<Self::Item> {
6160        if self.buf.len() == self.pos {
6161            return None;
6162        }
6163        let pos = self.pos;
6164        let mut r#type = None;
6165        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6166            r#type = Some(header.r#type);
6167            let res = match header.r#type {
6168                1u16 => OpPagePoolGetDumpReply::Id({
6169                    let res = parse_u32(next);
6170                    let Some(val) = res else { break };
6171                    val
6172                }),
6173                2u16 => OpPagePoolGetDumpReply::Ifindex({
6174                    let res = parse_u32(next);
6175                    let Some(val) = res else { break };
6176                    val
6177                }),
6178                3u16 => OpPagePoolGetDumpReply::NapiId({
6179                    let res = parse_u32(next);
6180                    let Some(val) = res else { break };
6181                    val
6182                }),
6183                4u16 => OpPagePoolGetDumpReply::Inflight({
6184                    let res = parse_u32(next);
6185                    let Some(val) = res else { break };
6186                    val
6187                }),
6188                5u16 => OpPagePoolGetDumpReply::InflightMem({
6189                    let res = parse_u32(next);
6190                    let Some(val) = res else { break };
6191                    val
6192                }),
6193                6u16 => OpPagePoolGetDumpReply::DetachTime({
6194                    let res = parse_u32(next);
6195                    let Some(val) = res else { break };
6196                    val
6197                }),
6198                7u16 => OpPagePoolGetDumpReply::Dmabuf({
6199                    let res = parse_u32(next);
6200                    let Some(val) = res else { break };
6201                    val
6202                }),
6203                8u16 => OpPagePoolGetDumpReply::IoUring({
6204                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6205                    let Some(val) = res else { break };
6206                    val
6207                }),
6208                n => {
6209                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
6210                        break;
6211                    } else {
6212                        continue;
6213                    }
6214                }
6215            };
6216            return Some(Ok(res));
6217        }
6218        Some(Err(ErrorContext::new(
6219            "OpPagePoolGetDumpReply",
6220            r#type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6221            self.orig_loc,
6222            self.buf.as_ptr().wrapping_add(pos) as usize,
6223        )))
6224    }
6225}
6226impl<'a> std::fmt::Debug for IterableOpPagePoolGetDumpReply<'_> {
6227    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6228        let mut fmt = f.debug_struct("OpPagePoolGetDumpReply");
6229        for attr in self.clone() {
6230            let attr = match attr {
6231                Ok(a) => a,
6232                Err(err) => {
6233                    fmt.finish()?;
6234                    f.write_str("Err(")?;
6235                    err.fmt(f)?;
6236                    return f.write_str(")");
6237                }
6238            };
6239            match attr {
6240                OpPagePoolGetDumpReply::Id(val) => fmt.field("Id", &val),
6241                OpPagePoolGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
6242                OpPagePoolGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
6243                OpPagePoolGetDumpReply::Inflight(val) => fmt.field("Inflight", &val),
6244                OpPagePoolGetDumpReply::InflightMem(val) => fmt.field("InflightMem", &val),
6245                OpPagePoolGetDumpReply::DetachTime(val) => fmt.field("DetachTime", &val),
6246                OpPagePoolGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6247                OpPagePoolGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
6248            };
6249        }
6250        fmt.finish()
6251    }
6252}
6253impl IterableOpPagePoolGetDumpReply<'_> {
6254    pub fn lookup_attr(
6255        &self,
6256        offset: usize,
6257        missing_type: Option<u16>,
6258    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6259        let mut stack = Vec::new();
6260        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6261        if cur == offset + PushBuiltinNfgenmsg::len() {
6262            stack.push(("OpPagePoolGetDumpReply", offset));
6263            return (
6264                stack,
6265                missing_type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6266            );
6267        }
6268        if cur > offset || cur + self.buf.len() < offset {
6269            return (stack, None);
6270        }
6271        let mut attrs = self.clone();
6272        let mut last_off = cur + attrs.pos;
6273        let mut missing = None;
6274        while let Some(attr) = attrs.next() {
6275            let Ok(attr) = attr else { break };
6276            match attr {
6277                OpPagePoolGetDumpReply::Id(val) => {
6278                    if last_off == offset {
6279                        stack.push(("Id", last_off));
6280                        break;
6281                    }
6282                }
6283                OpPagePoolGetDumpReply::Ifindex(val) => {
6284                    if last_off == offset {
6285                        stack.push(("Ifindex", last_off));
6286                        break;
6287                    }
6288                }
6289                OpPagePoolGetDumpReply::NapiId(val) => {
6290                    if last_off == offset {
6291                        stack.push(("NapiId", last_off));
6292                        break;
6293                    }
6294                }
6295                OpPagePoolGetDumpReply::Inflight(val) => {
6296                    if last_off == offset {
6297                        stack.push(("Inflight", last_off));
6298                        break;
6299                    }
6300                }
6301                OpPagePoolGetDumpReply::InflightMem(val) => {
6302                    if last_off == offset {
6303                        stack.push(("InflightMem", last_off));
6304                        break;
6305                    }
6306                }
6307                OpPagePoolGetDumpReply::DetachTime(val) => {
6308                    if last_off == offset {
6309                        stack.push(("DetachTime", last_off));
6310                        break;
6311                    }
6312                }
6313                OpPagePoolGetDumpReply::Dmabuf(val) => {
6314                    if last_off == offset {
6315                        stack.push(("Dmabuf", last_off));
6316                        break;
6317                    }
6318                }
6319                OpPagePoolGetDumpReply::IoUring(val) => {
6320                    (stack, missing) = val.lookup_attr(offset, missing_type);
6321                    if !stack.is_empty() {
6322                        break;
6323                    }
6324                }
6325                _ => {}
6326            };
6327            last_off = cur + attrs.pos;
6328        }
6329        if !stack.is_empty() {
6330            stack.push(("OpPagePoolGetDumpReply", cur));
6331        }
6332        (stack, missing)
6333    }
6334}
6335#[derive(Debug)]
6336pub struct RequestOpPagePoolGetDumpRequest<'r> {
6337    request: Request<'r>,
6338}
6339impl<'r> RequestOpPagePoolGetDumpRequest<'r> {
6340    pub fn new(mut request: Request<'r>) -> Self {
6341        PushOpPagePoolGetDumpRequest::write_header(&mut request.buf_mut());
6342        Self {
6343            request: request.set_dump(),
6344        }
6345    }
6346    pub fn encode(&mut self) -> PushOpPagePoolGetDumpRequest<&mut Vec<u8>> {
6347        PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf_mut())
6348    }
6349    pub fn into_encoder(self) -> PushOpPagePoolGetDumpRequest<RequestBuf<'r>> {
6350        PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf)
6351    }
6352}
6353impl NetlinkRequest for RequestOpPagePoolGetDumpRequest<'_> {
6354    type ReplyType<'buf> = IterableOpPagePoolGetDumpReply<'buf>;
6355    fn protocol(&self) -> Protocol {
6356        Protocol::Generic("netdev".as_bytes())
6357    }
6358    fn flags(&self) -> u16 {
6359        self.request.flags
6360    }
6361    fn payload(&self) -> &[u8] {
6362        self.request.buf()
6363    }
6364    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6365        OpPagePoolGetDumpReply::new(buf)
6366    }
6367    fn lookup(
6368        buf: &[u8],
6369        offset: usize,
6370        missing_type: Option<u16>,
6371    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6372        OpPagePoolGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
6373    }
6374}
6375#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6376pub struct PushOpPagePoolGetDoRequest<Prev: Rec> {
6377    pub(crate) prev: Option<Prev>,
6378    pub(crate) header_offset: Option<usize>,
6379}
6380impl<Prev: Rec> Rec for PushOpPagePoolGetDoRequest<Prev> {
6381    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6382        self.prev.as_mut().unwrap().as_rec_mut()
6383    }
6384}
6385impl<Prev: Rec> PushOpPagePoolGetDoRequest<Prev> {
6386    pub fn new(mut prev: Prev) -> Self {
6387        Self::write_header(&mut prev);
6388        Self::new_without_header(prev)
6389    }
6390    fn new_without_header(prev: Prev) -> Self {
6391        Self {
6392            prev: Some(prev),
6393            header_offset: None,
6394        }
6395    }
6396    fn write_header(prev: &mut Prev) {
6397        let mut header = PushBuiltinNfgenmsg::new();
6398        header.set_cmd(5u8);
6399        header.set_version(1u8);
6400        prev.as_rec_mut().extend(header.as_slice());
6401    }
6402    pub fn end_nested(mut self) -> Prev {
6403        let mut prev = self.prev.take().unwrap();
6404        if let Some(header_offset) = &self.header_offset {
6405            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6406        }
6407        prev
6408    }
6409    #[doc = "Unique ID of a Page Pool instance."]
6410    pub fn push_id(mut self, value: u32) -> Self {
6411        push_header(self.as_rec_mut(), 1u16, 4 as u16);
6412        self.as_rec_mut().extend(value.to_ne_bytes());
6413        self
6414    }
6415}
6416impl<Prev: Rec> Drop for PushOpPagePoolGetDoRequest<Prev> {
6417    fn drop(&mut self) {
6418        if let Some(prev) = &mut self.prev {
6419            if let Some(header_offset) = &self.header_offset {
6420                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6421            }
6422        }
6423    }
6424}
6425#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6426#[derive(Clone)]
6427pub enum OpPagePoolGetDoRequest {
6428    #[doc = "Unique ID of a Page Pool instance."]
6429    Id(u32),
6430}
6431impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6432    #[doc = "Unique ID of a Page Pool instance."]
6433    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6434        let mut iter = self.clone();
6435        iter.pos = 0;
6436        for attr in iter {
6437            if let OpPagePoolGetDoRequest::Id(val) = attr? {
6438                return Ok(val);
6439            }
6440        }
6441        Err(ErrorContext::new_missing(
6442            "OpPagePoolGetDoRequest",
6443            "Id",
6444            self.orig_loc,
6445            self.buf.as_ptr() as usize,
6446        ))
6447    }
6448}
6449impl OpPagePoolGetDoRequest {
6450    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoRequest<'a> {
6451        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6452        IterableOpPagePoolGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
6453    }
6454    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6455        PagePool::attr_from_type(r#type)
6456    }
6457}
6458#[derive(Clone, Copy, Default)]
6459pub struct IterableOpPagePoolGetDoRequest<'a> {
6460    buf: &'a [u8],
6461    pos: usize,
6462    orig_loc: usize,
6463}
6464impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6465    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6466        Self {
6467            buf,
6468            pos: 0,
6469            orig_loc,
6470        }
6471    }
6472    pub fn get_buf(&self) -> &'a [u8] {
6473        self.buf
6474    }
6475}
6476impl<'a> Iterator for IterableOpPagePoolGetDoRequest<'a> {
6477    type Item = Result<OpPagePoolGetDoRequest, ErrorContext>;
6478    fn next(&mut self) -> Option<Self::Item> {
6479        if self.buf.len() == self.pos {
6480            return None;
6481        }
6482        let pos = self.pos;
6483        let mut r#type = None;
6484        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6485            r#type = Some(header.r#type);
6486            let res = match header.r#type {
6487                1u16 => OpPagePoolGetDoRequest::Id({
6488                    let res = parse_u32(next);
6489                    let Some(val) = res else { break };
6490                    val
6491                }),
6492                n => {
6493                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
6494                        break;
6495                    } else {
6496                        continue;
6497                    }
6498                }
6499            };
6500            return Some(Ok(res));
6501        }
6502        Some(Err(ErrorContext::new(
6503            "OpPagePoolGetDoRequest",
6504            r#type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6505            self.orig_loc,
6506            self.buf.as_ptr().wrapping_add(pos) as usize,
6507        )))
6508    }
6509}
6510impl std::fmt::Debug for IterableOpPagePoolGetDoRequest<'_> {
6511    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6512        let mut fmt = f.debug_struct("OpPagePoolGetDoRequest");
6513        for attr in self.clone() {
6514            let attr = match attr {
6515                Ok(a) => a,
6516                Err(err) => {
6517                    fmt.finish()?;
6518                    f.write_str("Err(")?;
6519                    err.fmt(f)?;
6520                    return f.write_str(")");
6521                }
6522            };
6523            match attr {
6524                OpPagePoolGetDoRequest::Id(val) => fmt.field("Id", &val),
6525            };
6526        }
6527        fmt.finish()
6528    }
6529}
6530impl IterableOpPagePoolGetDoRequest<'_> {
6531    pub fn lookup_attr(
6532        &self,
6533        offset: usize,
6534        missing_type: Option<u16>,
6535    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6536        let mut stack = Vec::new();
6537        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6538        if cur == offset + PushBuiltinNfgenmsg::len() {
6539            stack.push(("OpPagePoolGetDoRequest", offset));
6540            return (
6541                stack,
6542                missing_type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6543            );
6544        }
6545        if cur > offset || cur + self.buf.len() < offset {
6546            return (stack, None);
6547        }
6548        let mut attrs = self.clone();
6549        let mut last_off = cur + attrs.pos;
6550        while let Some(attr) = attrs.next() {
6551            let Ok(attr) = attr else { break };
6552            match attr {
6553                OpPagePoolGetDoRequest::Id(val) => {
6554                    if last_off == offset {
6555                        stack.push(("Id", last_off));
6556                        break;
6557                    }
6558                }
6559                _ => {}
6560            };
6561            last_off = cur + attrs.pos;
6562        }
6563        if !stack.is_empty() {
6564            stack.push(("OpPagePoolGetDoRequest", cur));
6565        }
6566        (stack, None)
6567    }
6568}
6569#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6570pub struct PushOpPagePoolGetDoReply<Prev: Rec> {
6571    pub(crate) prev: Option<Prev>,
6572    pub(crate) header_offset: Option<usize>,
6573}
6574impl<Prev: Rec> Rec for PushOpPagePoolGetDoReply<Prev> {
6575    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6576        self.prev.as_mut().unwrap().as_rec_mut()
6577    }
6578}
6579impl<Prev: Rec> PushOpPagePoolGetDoReply<Prev> {
6580    pub fn new(mut prev: Prev) -> Self {
6581        Self::write_header(&mut prev);
6582        Self::new_without_header(prev)
6583    }
6584    fn new_without_header(prev: Prev) -> Self {
6585        Self {
6586            prev: Some(prev),
6587            header_offset: None,
6588        }
6589    }
6590    fn write_header(prev: &mut Prev) {
6591        let mut header = PushBuiltinNfgenmsg::new();
6592        header.set_cmd(5u8);
6593        header.set_version(1u8);
6594        prev.as_rec_mut().extend(header.as_slice());
6595    }
6596    pub fn end_nested(mut self) -> Prev {
6597        let mut prev = self.prev.take().unwrap();
6598        if let Some(header_offset) = &self.header_offset {
6599            finalize_nested_header(prev.as_rec_mut(), *header_offset);
6600        }
6601        prev
6602    }
6603    #[doc = "Unique ID of a Page Pool instance."]
6604    pub fn push_id(mut self, value: u32) -> Self {
6605        push_header(self.as_rec_mut(), 1u16, 4 as u16);
6606        self.as_rec_mut().extend(value.to_ne_bytes());
6607        self
6608    }
6609    #[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"]
6610    pub fn push_ifindex(mut self, value: u32) -> Self {
6611        push_header(self.as_rec_mut(), 2u16, 4 as u16);
6612        self.as_rec_mut().extend(value.to_ne_bytes());
6613        self
6614    }
6615    #[doc = "Id of NAPI using this Page Pool instance."]
6616    pub fn push_napi_id(mut self, value: u32) -> Self {
6617        push_header(self.as_rec_mut(), 3u16, 4 as u16);
6618        self.as_rec_mut().extend(value.to_ne_bytes());
6619        self
6620    }
6621    #[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"]
6622    pub fn push_inflight(mut self, value: u32) -> Self {
6623        push_header(self.as_rec_mut(), 4u16, 4 as u16);
6624        self.as_rec_mut().extend(value.to_ne_bytes());
6625        self
6626    }
6627    #[doc = "Amount of memory held by inflight pages.\n"]
6628    pub fn push_inflight_mem(mut self, value: u32) -> Self {
6629        push_header(self.as_rec_mut(), 5u16, 4 as u16);
6630        self.as_rec_mut().extend(value.to_ne_bytes());
6631        self
6632    }
6633    #[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"]
6634    pub fn push_detach_time(mut self, value: u32) -> Self {
6635        push_header(self.as_rec_mut(), 6u16, 4 as u16);
6636        self.as_rec_mut().extend(value.to_ne_bytes());
6637        self
6638    }
6639    #[doc = "ID of the dmabuf this page-pool is attached to."]
6640    pub fn push_dmabuf(mut self, value: u32) -> Self {
6641        push_header(self.as_rec_mut(), 7u16, 4 as u16);
6642        self.as_rec_mut().extend(value.to_ne_bytes());
6643        self
6644    }
6645    #[doc = "io-uring memory provider information."]
6646    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6647        let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6648        PushIoUringProviderInfo {
6649            prev: Some(self),
6650            header_offset: Some(header_offset),
6651        }
6652    }
6653}
6654impl<Prev: Rec> Drop for PushOpPagePoolGetDoReply<Prev> {
6655    fn drop(&mut self) {
6656        if let Some(prev) = &mut self.prev {
6657            if let Some(header_offset) = &self.header_offset {
6658                finalize_nested_header(prev.as_rec_mut(), *header_offset);
6659            }
6660        }
6661    }
6662}
6663#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6664#[derive(Clone)]
6665pub enum OpPagePoolGetDoReply<'a> {
6666    #[doc = "Unique ID of a Page Pool instance."]
6667    Id(u32),
6668    #[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"]
6669    Ifindex(u32),
6670    #[doc = "Id of NAPI using this Page Pool instance."]
6671    NapiId(u32),
6672    #[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"]
6673    Inflight(u32),
6674    #[doc = "Amount of memory held by inflight pages.\n"]
6675    InflightMem(u32),
6676    #[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"]
6677    DetachTime(u32),
6678    #[doc = "ID of the dmabuf this page-pool is attached to."]
6679    Dmabuf(u32),
6680    #[doc = "io-uring memory provider information."]
6681    IoUring(IterableIoUringProviderInfo<'a>),
6682}
6683impl<'a> IterableOpPagePoolGetDoReply<'a> {
6684    #[doc = "Unique ID of a Page Pool instance."]
6685    pub fn get_id(&self) -> Result<u32, ErrorContext> {
6686        let mut iter = self.clone();
6687        iter.pos = 0;
6688        for attr in iter {
6689            if let OpPagePoolGetDoReply::Id(val) = attr? {
6690                return Ok(val);
6691            }
6692        }
6693        Err(ErrorContext::new_missing(
6694            "OpPagePoolGetDoReply",
6695            "Id",
6696            self.orig_loc,
6697            self.buf.as_ptr() as usize,
6698        ))
6699    }
6700    #[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"]
6701    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6702        let mut iter = self.clone();
6703        iter.pos = 0;
6704        for attr in iter {
6705            if let OpPagePoolGetDoReply::Ifindex(val) = attr? {
6706                return Ok(val);
6707            }
6708        }
6709        Err(ErrorContext::new_missing(
6710            "OpPagePoolGetDoReply",
6711            "Ifindex",
6712            self.orig_loc,
6713            self.buf.as_ptr() as usize,
6714        ))
6715    }
6716    #[doc = "Id of NAPI using this Page Pool instance."]
6717    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6718        let mut iter = self.clone();
6719        iter.pos = 0;
6720        for attr in iter {
6721            if let OpPagePoolGetDoReply::NapiId(val) = attr? {
6722                return Ok(val);
6723            }
6724        }
6725        Err(ErrorContext::new_missing(
6726            "OpPagePoolGetDoReply",
6727            "NapiId",
6728            self.orig_loc,
6729            self.buf.as_ptr() as usize,
6730        ))
6731    }
6732    #[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"]
6733    pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6734        let mut iter = self.clone();
6735        iter.pos = 0;
6736        for attr in iter {
6737            if let OpPagePoolGetDoReply::Inflight(val) = attr? {
6738                return Ok(val);
6739            }
6740        }
6741        Err(ErrorContext::new_missing(
6742            "OpPagePoolGetDoReply",
6743            "Inflight",
6744            self.orig_loc,
6745            self.buf.as_ptr() as usize,
6746        ))
6747    }
6748    #[doc = "Amount of memory held by inflight pages.\n"]
6749    pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6750        let mut iter = self.clone();
6751        iter.pos = 0;
6752        for attr in iter {
6753            if let OpPagePoolGetDoReply::InflightMem(val) = attr? {
6754                return Ok(val);
6755            }
6756        }
6757        Err(ErrorContext::new_missing(
6758            "OpPagePoolGetDoReply",
6759            "InflightMem",
6760            self.orig_loc,
6761            self.buf.as_ptr() as usize,
6762        ))
6763    }
6764    #[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"]
6765    pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6766        let mut iter = self.clone();
6767        iter.pos = 0;
6768        for attr in iter {
6769            if let OpPagePoolGetDoReply::DetachTime(val) = attr? {
6770                return Ok(val);
6771            }
6772        }
6773        Err(ErrorContext::new_missing(
6774            "OpPagePoolGetDoReply",
6775            "DetachTime",
6776            self.orig_loc,
6777            self.buf.as_ptr() as usize,
6778        ))
6779    }
6780    #[doc = "ID of the dmabuf this page-pool is attached to."]
6781    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6782        let mut iter = self.clone();
6783        iter.pos = 0;
6784        for attr in iter {
6785            if let OpPagePoolGetDoReply::Dmabuf(val) = attr? {
6786                return Ok(val);
6787            }
6788        }
6789        Err(ErrorContext::new_missing(
6790            "OpPagePoolGetDoReply",
6791            "Dmabuf",
6792            self.orig_loc,
6793            self.buf.as_ptr() as usize,
6794        ))
6795    }
6796    #[doc = "io-uring memory provider information."]
6797    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6798        let mut iter = self.clone();
6799        iter.pos = 0;
6800        for attr in iter {
6801            if let OpPagePoolGetDoReply::IoUring(val) = attr? {
6802                return Ok(val);
6803            }
6804        }
6805        Err(ErrorContext::new_missing(
6806            "OpPagePoolGetDoReply",
6807            "IoUring",
6808            self.orig_loc,
6809            self.buf.as_ptr() as usize,
6810        ))
6811    }
6812}
6813impl OpPagePoolGetDoReply<'_> {
6814    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoReply<'a> {
6815        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6816        IterableOpPagePoolGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
6817    }
6818    fn attr_from_type(r#type: u16) -> Option<&'static str> {
6819        PagePool::attr_from_type(r#type)
6820    }
6821}
6822#[derive(Clone, Copy, Default)]
6823pub struct IterableOpPagePoolGetDoReply<'a> {
6824    buf: &'a [u8],
6825    pos: usize,
6826    orig_loc: usize,
6827}
6828impl<'a> IterableOpPagePoolGetDoReply<'a> {
6829    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6830        Self {
6831            buf,
6832            pos: 0,
6833            orig_loc,
6834        }
6835    }
6836    pub fn get_buf(&self) -> &'a [u8] {
6837        self.buf
6838    }
6839}
6840impl<'a> Iterator for IterableOpPagePoolGetDoReply<'a> {
6841    type Item = Result<OpPagePoolGetDoReply<'a>, ErrorContext>;
6842    fn next(&mut self) -> Option<Self::Item> {
6843        if self.buf.len() == self.pos {
6844            return None;
6845        }
6846        let pos = self.pos;
6847        let mut r#type = None;
6848        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6849            r#type = Some(header.r#type);
6850            let res = match header.r#type {
6851                1u16 => OpPagePoolGetDoReply::Id({
6852                    let res = parse_u32(next);
6853                    let Some(val) = res else { break };
6854                    val
6855                }),
6856                2u16 => OpPagePoolGetDoReply::Ifindex({
6857                    let res = parse_u32(next);
6858                    let Some(val) = res else { break };
6859                    val
6860                }),
6861                3u16 => OpPagePoolGetDoReply::NapiId({
6862                    let res = parse_u32(next);
6863                    let Some(val) = res else { break };
6864                    val
6865                }),
6866                4u16 => OpPagePoolGetDoReply::Inflight({
6867                    let res = parse_u32(next);
6868                    let Some(val) = res else { break };
6869                    val
6870                }),
6871                5u16 => OpPagePoolGetDoReply::InflightMem({
6872                    let res = parse_u32(next);
6873                    let Some(val) = res else { break };
6874                    val
6875                }),
6876                6u16 => OpPagePoolGetDoReply::DetachTime({
6877                    let res = parse_u32(next);
6878                    let Some(val) = res else { break };
6879                    val
6880                }),
6881                7u16 => OpPagePoolGetDoReply::Dmabuf({
6882                    let res = parse_u32(next);
6883                    let Some(val) = res else { break };
6884                    val
6885                }),
6886                8u16 => OpPagePoolGetDoReply::IoUring({
6887                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6888                    let Some(val) = res else { break };
6889                    val
6890                }),
6891                n => {
6892                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
6893                        break;
6894                    } else {
6895                        continue;
6896                    }
6897                }
6898            };
6899            return Some(Ok(res));
6900        }
6901        Some(Err(ErrorContext::new(
6902            "OpPagePoolGetDoReply",
6903            r#type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6904            self.orig_loc,
6905            self.buf.as_ptr().wrapping_add(pos) as usize,
6906        )))
6907    }
6908}
6909impl<'a> std::fmt::Debug for IterableOpPagePoolGetDoReply<'_> {
6910    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6911        let mut fmt = f.debug_struct("OpPagePoolGetDoReply");
6912        for attr in self.clone() {
6913            let attr = match attr {
6914                Ok(a) => a,
6915                Err(err) => {
6916                    fmt.finish()?;
6917                    f.write_str("Err(")?;
6918                    err.fmt(f)?;
6919                    return f.write_str(")");
6920                }
6921            };
6922            match attr {
6923                OpPagePoolGetDoReply::Id(val) => fmt.field("Id", &val),
6924                OpPagePoolGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
6925                OpPagePoolGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
6926                OpPagePoolGetDoReply::Inflight(val) => fmt.field("Inflight", &val),
6927                OpPagePoolGetDoReply::InflightMem(val) => fmt.field("InflightMem", &val),
6928                OpPagePoolGetDoReply::DetachTime(val) => fmt.field("DetachTime", &val),
6929                OpPagePoolGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6930                OpPagePoolGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
6931            };
6932        }
6933        fmt.finish()
6934    }
6935}
6936impl IterableOpPagePoolGetDoReply<'_> {
6937    pub fn lookup_attr(
6938        &self,
6939        offset: usize,
6940        missing_type: Option<u16>,
6941    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6942        let mut stack = Vec::new();
6943        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6944        if cur == offset + PushBuiltinNfgenmsg::len() {
6945            stack.push(("OpPagePoolGetDoReply", offset));
6946            return (
6947                stack,
6948                missing_type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6949            );
6950        }
6951        if cur > offset || cur + self.buf.len() < offset {
6952            return (stack, None);
6953        }
6954        let mut attrs = self.clone();
6955        let mut last_off = cur + attrs.pos;
6956        let mut missing = None;
6957        while let Some(attr) = attrs.next() {
6958            let Ok(attr) = attr else { break };
6959            match attr {
6960                OpPagePoolGetDoReply::Id(val) => {
6961                    if last_off == offset {
6962                        stack.push(("Id", last_off));
6963                        break;
6964                    }
6965                }
6966                OpPagePoolGetDoReply::Ifindex(val) => {
6967                    if last_off == offset {
6968                        stack.push(("Ifindex", last_off));
6969                        break;
6970                    }
6971                }
6972                OpPagePoolGetDoReply::NapiId(val) => {
6973                    if last_off == offset {
6974                        stack.push(("NapiId", last_off));
6975                        break;
6976                    }
6977                }
6978                OpPagePoolGetDoReply::Inflight(val) => {
6979                    if last_off == offset {
6980                        stack.push(("Inflight", last_off));
6981                        break;
6982                    }
6983                }
6984                OpPagePoolGetDoReply::InflightMem(val) => {
6985                    if last_off == offset {
6986                        stack.push(("InflightMem", last_off));
6987                        break;
6988                    }
6989                }
6990                OpPagePoolGetDoReply::DetachTime(val) => {
6991                    if last_off == offset {
6992                        stack.push(("DetachTime", last_off));
6993                        break;
6994                    }
6995                }
6996                OpPagePoolGetDoReply::Dmabuf(val) => {
6997                    if last_off == offset {
6998                        stack.push(("Dmabuf", last_off));
6999                        break;
7000                    }
7001                }
7002                OpPagePoolGetDoReply::IoUring(val) => {
7003                    (stack, missing) = val.lookup_attr(offset, missing_type);
7004                    if !stack.is_empty() {
7005                        break;
7006                    }
7007                }
7008                _ => {}
7009            };
7010            last_off = cur + attrs.pos;
7011        }
7012        if !stack.is_empty() {
7013            stack.push(("OpPagePoolGetDoReply", cur));
7014        }
7015        (stack, missing)
7016    }
7017}
7018#[derive(Debug)]
7019pub struct RequestOpPagePoolGetDoRequest<'r> {
7020    request: Request<'r>,
7021}
7022impl<'r> RequestOpPagePoolGetDoRequest<'r> {
7023    pub fn new(mut request: Request<'r>) -> Self {
7024        PushOpPagePoolGetDoRequest::write_header(&mut request.buf_mut());
7025        Self { request: request }
7026    }
7027    pub fn encode(&mut self) -> PushOpPagePoolGetDoRequest<&mut Vec<u8>> {
7028        PushOpPagePoolGetDoRequest::new_without_header(self.request.buf_mut())
7029    }
7030    pub fn into_encoder(self) -> PushOpPagePoolGetDoRequest<RequestBuf<'r>> {
7031        PushOpPagePoolGetDoRequest::new_without_header(self.request.buf)
7032    }
7033}
7034impl NetlinkRequest for RequestOpPagePoolGetDoRequest<'_> {
7035    type ReplyType<'buf> = IterableOpPagePoolGetDoReply<'buf>;
7036    fn protocol(&self) -> Protocol {
7037        Protocol::Generic("netdev".as_bytes())
7038    }
7039    fn flags(&self) -> u16 {
7040        self.request.flags
7041    }
7042    fn payload(&self) -> &[u8] {
7043        self.request.buf()
7044    }
7045    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7046        OpPagePoolGetDoReply::new(buf)
7047    }
7048    fn lookup(
7049        buf: &[u8],
7050        offset: usize,
7051        missing_type: Option<u16>,
7052    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7053        OpPagePoolGetDoRequest::new(buf).lookup_attr(offset, missing_type)
7054    }
7055}
7056#[doc = "Get page pool statistics."]
7057pub struct PushOpPagePoolStatsGetDumpRequest<Prev: Rec> {
7058    pub(crate) prev: Option<Prev>,
7059    pub(crate) header_offset: Option<usize>,
7060}
7061impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpRequest<Prev> {
7062    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7063        self.prev.as_mut().unwrap().as_rec_mut()
7064    }
7065}
7066impl<Prev: Rec> PushOpPagePoolStatsGetDumpRequest<Prev> {
7067    pub fn new(mut prev: Prev) -> Self {
7068        Self::write_header(&mut prev);
7069        Self::new_without_header(prev)
7070    }
7071    fn new_without_header(prev: Prev) -> Self {
7072        Self {
7073            prev: Some(prev),
7074            header_offset: None,
7075        }
7076    }
7077    fn write_header(prev: &mut Prev) {
7078        let mut header = PushBuiltinNfgenmsg::new();
7079        header.set_cmd(9u8);
7080        header.set_version(1u8);
7081        prev.as_rec_mut().extend(header.as_slice());
7082    }
7083    pub fn end_nested(mut self) -> Prev {
7084        let mut prev = self.prev.take().unwrap();
7085        if let Some(header_offset) = &self.header_offset {
7086            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7087        }
7088        prev
7089    }
7090}
7091impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpRequest<Prev> {
7092    fn drop(&mut self) {
7093        if let Some(prev) = &mut self.prev {
7094            if let Some(header_offset) = &self.header_offset {
7095                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7096            }
7097        }
7098    }
7099}
7100#[doc = "Get page pool statistics."]
7101#[derive(Clone)]
7102pub enum OpPagePoolStatsGetDumpRequest {}
7103impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {}
7104impl OpPagePoolStatsGetDumpRequest {
7105    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'a> {
7106        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7107        IterableOpPagePoolStatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
7108    }
7109    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7110        PagePoolStats::attr_from_type(r#type)
7111    }
7112}
7113#[derive(Clone, Copy, Default)]
7114pub struct IterableOpPagePoolStatsGetDumpRequest<'a> {
7115    buf: &'a [u8],
7116    pos: usize,
7117    orig_loc: usize,
7118}
7119impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {
7120    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7121        Self {
7122            buf,
7123            pos: 0,
7124            orig_loc,
7125        }
7126    }
7127    pub fn get_buf(&self) -> &'a [u8] {
7128        self.buf
7129    }
7130}
7131impl<'a> Iterator for IterableOpPagePoolStatsGetDumpRequest<'a> {
7132    type Item = Result<OpPagePoolStatsGetDumpRequest, ErrorContext>;
7133    fn next(&mut self) -> Option<Self::Item> {
7134        if self.buf.len() == self.pos {
7135            return None;
7136        }
7137        let pos = self.pos;
7138        let mut r#type = None;
7139        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7140            r#type = Some(header.r#type);
7141            let res = match header.r#type {
7142                n => {
7143                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
7144                        break;
7145                    } else {
7146                        continue;
7147                    }
7148                }
7149            };
7150            return Some(Ok(res));
7151        }
7152        Some(Err(ErrorContext::new(
7153            "OpPagePoolStatsGetDumpRequest",
7154            r#type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7155            self.orig_loc,
7156            self.buf.as_ptr().wrapping_add(pos) as usize,
7157        )))
7158    }
7159}
7160impl std::fmt::Debug for IterableOpPagePoolStatsGetDumpRequest<'_> {
7161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7162        let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpRequest");
7163        for attr in self.clone() {
7164            let attr = match attr {
7165                Ok(a) => a,
7166                Err(err) => {
7167                    fmt.finish()?;
7168                    f.write_str("Err(")?;
7169                    err.fmt(f)?;
7170                    return f.write_str(")");
7171                }
7172            };
7173            match attr {};
7174        }
7175        fmt.finish()
7176    }
7177}
7178impl IterableOpPagePoolStatsGetDumpRequest<'_> {
7179    pub fn lookup_attr(
7180        &self,
7181        offset: usize,
7182        missing_type: Option<u16>,
7183    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7184        let mut stack = Vec::new();
7185        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7186        if cur == offset + PushBuiltinNfgenmsg::len() {
7187            stack.push(("OpPagePoolStatsGetDumpRequest", offset));
7188            return (
7189                stack,
7190                missing_type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7191            );
7192        }
7193        (stack, None)
7194    }
7195}
7196#[doc = "Get page pool statistics."]
7197pub struct PushOpPagePoolStatsGetDumpReply<Prev: Rec> {
7198    pub(crate) prev: Option<Prev>,
7199    pub(crate) header_offset: Option<usize>,
7200}
7201impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpReply<Prev> {
7202    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7203        self.prev.as_mut().unwrap().as_rec_mut()
7204    }
7205}
7206impl<Prev: Rec> PushOpPagePoolStatsGetDumpReply<Prev> {
7207    pub fn new(mut prev: Prev) -> Self {
7208        Self::write_header(&mut prev);
7209        Self::new_without_header(prev)
7210    }
7211    fn new_without_header(prev: Prev) -> Self {
7212        Self {
7213            prev: Some(prev),
7214            header_offset: None,
7215        }
7216    }
7217    fn write_header(prev: &mut Prev) {
7218        let mut header = PushBuiltinNfgenmsg::new();
7219        header.set_cmd(9u8);
7220        header.set_version(1u8);
7221        prev.as_rec_mut().extend(header.as_slice());
7222    }
7223    pub fn end_nested(mut self) -> Prev {
7224        let mut prev = self.prev.take().unwrap();
7225        if let Some(header_offset) = &self.header_offset {
7226            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7227        }
7228        prev
7229    }
7230    #[doc = "Page pool identifying information."]
7231    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7232        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7233        PushPagePoolInfo {
7234            prev: Some(self),
7235            header_offset: Some(header_offset),
7236        }
7237    }
7238    pub fn push_alloc_fast(mut self, value: u32) -> Self {
7239        push_header(self.as_rec_mut(), 8u16, 4 as u16);
7240        self.as_rec_mut().extend(value.to_ne_bytes());
7241        self
7242    }
7243    pub fn push_alloc_slow(mut self, value: u32) -> Self {
7244        push_header(self.as_rec_mut(), 9u16, 4 as u16);
7245        self.as_rec_mut().extend(value.to_ne_bytes());
7246        self
7247    }
7248    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
7249        push_header(self.as_rec_mut(), 10u16, 4 as u16);
7250        self.as_rec_mut().extend(value.to_ne_bytes());
7251        self
7252    }
7253    pub fn push_alloc_empty(mut self, value: u32) -> Self {
7254        push_header(self.as_rec_mut(), 11u16, 4 as u16);
7255        self.as_rec_mut().extend(value.to_ne_bytes());
7256        self
7257    }
7258    pub fn push_alloc_refill(mut self, value: u32) -> Self {
7259        push_header(self.as_rec_mut(), 12u16, 4 as u16);
7260        self.as_rec_mut().extend(value.to_ne_bytes());
7261        self
7262    }
7263    pub fn push_alloc_waive(mut self, value: u32) -> Self {
7264        push_header(self.as_rec_mut(), 13u16, 4 as u16);
7265        self.as_rec_mut().extend(value.to_ne_bytes());
7266        self
7267    }
7268    pub fn push_recycle_cached(mut self, value: u32) -> Self {
7269        push_header(self.as_rec_mut(), 14u16, 4 as u16);
7270        self.as_rec_mut().extend(value.to_ne_bytes());
7271        self
7272    }
7273    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
7274        push_header(self.as_rec_mut(), 15u16, 4 as u16);
7275        self.as_rec_mut().extend(value.to_ne_bytes());
7276        self
7277    }
7278    pub fn push_recycle_ring(mut self, value: u32) -> Self {
7279        push_header(self.as_rec_mut(), 16u16, 4 as u16);
7280        self.as_rec_mut().extend(value.to_ne_bytes());
7281        self
7282    }
7283    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
7284        push_header(self.as_rec_mut(), 17u16, 4 as u16);
7285        self.as_rec_mut().extend(value.to_ne_bytes());
7286        self
7287    }
7288    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
7289        push_header(self.as_rec_mut(), 18u16, 4 as u16);
7290        self.as_rec_mut().extend(value.to_ne_bytes());
7291        self
7292    }
7293}
7294impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpReply<Prev> {
7295    fn drop(&mut self) {
7296        if let Some(prev) = &mut self.prev {
7297            if let Some(header_offset) = &self.header_offset {
7298                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7299            }
7300        }
7301    }
7302}
7303#[doc = "Get page pool statistics."]
7304#[derive(Clone)]
7305pub enum OpPagePoolStatsGetDumpReply<'a> {
7306    #[doc = "Page pool identifying information."]
7307    Info(IterablePagePoolInfo<'a>),
7308    AllocFast(u32),
7309    AllocSlow(u32),
7310    AllocSlowHighOrder(u32),
7311    AllocEmpty(u32),
7312    AllocRefill(u32),
7313    AllocWaive(u32),
7314    RecycleCached(u32),
7315    RecycleCacheFull(u32),
7316    RecycleRing(u32),
7317    RecycleRingFull(u32),
7318    RecycleReleasedRefcnt(u32),
7319}
7320impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7321    #[doc = "Page pool identifying information."]
7322    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7323        let mut iter = self.clone();
7324        iter.pos = 0;
7325        for attr in iter {
7326            if let OpPagePoolStatsGetDumpReply::Info(val) = attr? {
7327                return Ok(val);
7328            }
7329        }
7330        Err(ErrorContext::new_missing(
7331            "OpPagePoolStatsGetDumpReply",
7332            "Info",
7333            self.orig_loc,
7334            self.buf.as_ptr() as usize,
7335        ))
7336    }
7337    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
7338        let mut iter = self.clone();
7339        iter.pos = 0;
7340        for attr in iter {
7341            if let OpPagePoolStatsGetDumpReply::AllocFast(val) = attr? {
7342                return Ok(val);
7343            }
7344        }
7345        Err(ErrorContext::new_missing(
7346            "OpPagePoolStatsGetDumpReply",
7347            "AllocFast",
7348            self.orig_loc,
7349            self.buf.as_ptr() as usize,
7350        ))
7351    }
7352    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
7353        let mut iter = self.clone();
7354        iter.pos = 0;
7355        for attr in iter {
7356            if let OpPagePoolStatsGetDumpReply::AllocSlow(val) = attr? {
7357                return Ok(val);
7358            }
7359        }
7360        Err(ErrorContext::new_missing(
7361            "OpPagePoolStatsGetDumpReply",
7362            "AllocSlow",
7363            self.orig_loc,
7364            self.buf.as_ptr() as usize,
7365        ))
7366    }
7367    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
7368        let mut iter = self.clone();
7369        iter.pos = 0;
7370        for attr in iter {
7371            if let OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) = attr? {
7372                return Ok(val);
7373            }
7374        }
7375        Err(ErrorContext::new_missing(
7376            "OpPagePoolStatsGetDumpReply",
7377            "AllocSlowHighOrder",
7378            self.orig_loc,
7379            self.buf.as_ptr() as usize,
7380        ))
7381    }
7382    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
7383        let mut iter = self.clone();
7384        iter.pos = 0;
7385        for attr in iter {
7386            if let OpPagePoolStatsGetDumpReply::AllocEmpty(val) = attr? {
7387                return Ok(val);
7388            }
7389        }
7390        Err(ErrorContext::new_missing(
7391            "OpPagePoolStatsGetDumpReply",
7392            "AllocEmpty",
7393            self.orig_loc,
7394            self.buf.as_ptr() as usize,
7395        ))
7396    }
7397    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
7398        let mut iter = self.clone();
7399        iter.pos = 0;
7400        for attr in iter {
7401            if let OpPagePoolStatsGetDumpReply::AllocRefill(val) = attr? {
7402                return Ok(val);
7403            }
7404        }
7405        Err(ErrorContext::new_missing(
7406            "OpPagePoolStatsGetDumpReply",
7407            "AllocRefill",
7408            self.orig_loc,
7409            self.buf.as_ptr() as usize,
7410        ))
7411    }
7412    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
7413        let mut iter = self.clone();
7414        iter.pos = 0;
7415        for attr in iter {
7416            if let OpPagePoolStatsGetDumpReply::AllocWaive(val) = attr? {
7417                return Ok(val);
7418            }
7419        }
7420        Err(ErrorContext::new_missing(
7421            "OpPagePoolStatsGetDumpReply",
7422            "AllocWaive",
7423            self.orig_loc,
7424            self.buf.as_ptr() as usize,
7425        ))
7426    }
7427    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
7428        let mut iter = self.clone();
7429        iter.pos = 0;
7430        for attr in iter {
7431            if let OpPagePoolStatsGetDumpReply::RecycleCached(val) = attr? {
7432                return Ok(val);
7433            }
7434        }
7435        Err(ErrorContext::new_missing(
7436            "OpPagePoolStatsGetDumpReply",
7437            "RecycleCached",
7438            self.orig_loc,
7439            self.buf.as_ptr() as usize,
7440        ))
7441    }
7442    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
7443        let mut iter = self.clone();
7444        iter.pos = 0;
7445        for attr in iter {
7446            if let OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) = attr? {
7447                return Ok(val);
7448            }
7449        }
7450        Err(ErrorContext::new_missing(
7451            "OpPagePoolStatsGetDumpReply",
7452            "RecycleCacheFull",
7453            self.orig_loc,
7454            self.buf.as_ptr() as usize,
7455        ))
7456    }
7457    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
7458        let mut iter = self.clone();
7459        iter.pos = 0;
7460        for attr in iter {
7461            if let OpPagePoolStatsGetDumpReply::RecycleRing(val) = attr? {
7462                return Ok(val);
7463            }
7464        }
7465        Err(ErrorContext::new_missing(
7466            "OpPagePoolStatsGetDumpReply",
7467            "RecycleRing",
7468            self.orig_loc,
7469            self.buf.as_ptr() as usize,
7470        ))
7471    }
7472    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
7473        let mut iter = self.clone();
7474        iter.pos = 0;
7475        for attr in iter {
7476            if let OpPagePoolStatsGetDumpReply::RecycleRingFull(val) = attr? {
7477                return Ok(val);
7478            }
7479        }
7480        Err(ErrorContext::new_missing(
7481            "OpPagePoolStatsGetDumpReply",
7482            "RecycleRingFull",
7483            self.orig_loc,
7484            self.buf.as_ptr() as usize,
7485        ))
7486    }
7487    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
7488        let mut iter = self.clone();
7489        iter.pos = 0;
7490        for attr in iter {
7491            if let OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) = attr? {
7492                return Ok(val);
7493            }
7494        }
7495        Err(ErrorContext::new_missing(
7496            "OpPagePoolStatsGetDumpReply",
7497            "RecycleReleasedRefcnt",
7498            self.orig_loc,
7499            self.buf.as_ptr() as usize,
7500        ))
7501    }
7502}
7503impl OpPagePoolStatsGetDumpReply<'_> {
7504    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpReply<'a> {
7505        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7506        IterableOpPagePoolStatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
7507    }
7508    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7509        PagePoolStats::attr_from_type(r#type)
7510    }
7511}
7512#[derive(Clone, Copy, Default)]
7513pub struct IterableOpPagePoolStatsGetDumpReply<'a> {
7514    buf: &'a [u8],
7515    pos: usize,
7516    orig_loc: usize,
7517}
7518impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7519    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7520        Self {
7521            buf,
7522            pos: 0,
7523            orig_loc,
7524        }
7525    }
7526    pub fn get_buf(&self) -> &'a [u8] {
7527        self.buf
7528    }
7529}
7530impl<'a> Iterator for IterableOpPagePoolStatsGetDumpReply<'a> {
7531    type Item = Result<OpPagePoolStatsGetDumpReply<'a>, ErrorContext>;
7532    fn next(&mut self) -> Option<Self::Item> {
7533        if self.buf.len() == self.pos {
7534            return None;
7535        }
7536        let pos = self.pos;
7537        let mut r#type = None;
7538        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7539            r#type = Some(header.r#type);
7540            let res = match header.r#type {
7541                1u16 => OpPagePoolStatsGetDumpReply::Info({
7542                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7543                    let Some(val) = res else { break };
7544                    val
7545                }),
7546                8u16 => OpPagePoolStatsGetDumpReply::AllocFast({
7547                    let res = parse_u32(next);
7548                    let Some(val) = res else { break };
7549                    val
7550                }),
7551                9u16 => OpPagePoolStatsGetDumpReply::AllocSlow({
7552                    let res = parse_u32(next);
7553                    let Some(val) = res else { break };
7554                    val
7555                }),
7556                10u16 => OpPagePoolStatsGetDumpReply::AllocSlowHighOrder({
7557                    let res = parse_u32(next);
7558                    let Some(val) = res else { break };
7559                    val
7560                }),
7561                11u16 => OpPagePoolStatsGetDumpReply::AllocEmpty({
7562                    let res = parse_u32(next);
7563                    let Some(val) = res else { break };
7564                    val
7565                }),
7566                12u16 => OpPagePoolStatsGetDumpReply::AllocRefill({
7567                    let res = parse_u32(next);
7568                    let Some(val) = res else { break };
7569                    val
7570                }),
7571                13u16 => OpPagePoolStatsGetDumpReply::AllocWaive({
7572                    let res = parse_u32(next);
7573                    let Some(val) = res else { break };
7574                    val
7575                }),
7576                14u16 => OpPagePoolStatsGetDumpReply::RecycleCached({
7577                    let res = parse_u32(next);
7578                    let Some(val) = res else { break };
7579                    val
7580                }),
7581                15u16 => OpPagePoolStatsGetDumpReply::RecycleCacheFull({
7582                    let res = parse_u32(next);
7583                    let Some(val) = res else { break };
7584                    val
7585                }),
7586                16u16 => OpPagePoolStatsGetDumpReply::RecycleRing({
7587                    let res = parse_u32(next);
7588                    let Some(val) = res else { break };
7589                    val
7590                }),
7591                17u16 => OpPagePoolStatsGetDumpReply::RecycleRingFull({
7592                    let res = parse_u32(next);
7593                    let Some(val) = res else { break };
7594                    val
7595                }),
7596                18u16 => OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt({
7597                    let res = parse_u32(next);
7598                    let Some(val) = res else { break };
7599                    val
7600                }),
7601                n => {
7602                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
7603                        break;
7604                    } else {
7605                        continue;
7606                    }
7607                }
7608            };
7609            return Some(Ok(res));
7610        }
7611        Some(Err(ErrorContext::new(
7612            "OpPagePoolStatsGetDumpReply",
7613            r#type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7614            self.orig_loc,
7615            self.buf.as_ptr().wrapping_add(pos) as usize,
7616        )))
7617    }
7618}
7619impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDumpReply<'_> {
7620    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7621        let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpReply");
7622        for attr in self.clone() {
7623            let attr = match attr {
7624                Ok(a) => a,
7625                Err(err) => {
7626                    fmt.finish()?;
7627                    f.write_str("Err(")?;
7628                    err.fmt(f)?;
7629                    return f.write_str(")");
7630                }
7631            };
7632            match attr {
7633                OpPagePoolStatsGetDumpReply::Info(val) => fmt.field("Info", &val),
7634                OpPagePoolStatsGetDumpReply::AllocFast(val) => fmt.field("AllocFast", &val),
7635                OpPagePoolStatsGetDumpReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
7636                OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7637                    fmt.field("AllocSlowHighOrder", &val)
7638                }
7639                OpPagePoolStatsGetDumpReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
7640                OpPagePoolStatsGetDumpReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
7641                OpPagePoolStatsGetDumpReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
7642                OpPagePoolStatsGetDumpReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
7643                OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7644                    fmt.field("RecycleCacheFull", &val)
7645                }
7646                OpPagePoolStatsGetDumpReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
7647                OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7648                    fmt.field("RecycleRingFull", &val)
7649                }
7650                OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7651                    fmt.field("RecycleReleasedRefcnt", &val)
7652                }
7653            };
7654        }
7655        fmt.finish()
7656    }
7657}
7658impl IterableOpPagePoolStatsGetDumpReply<'_> {
7659    pub fn lookup_attr(
7660        &self,
7661        offset: usize,
7662        missing_type: Option<u16>,
7663    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7664        let mut stack = Vec::new();
7665        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7666        if cur == offset + PushBuiltinNfgenmsg::len() {
7667            stack.push(("OpPagePoolStatsGetDumpReply", offset));
7668            return (
7669                stack,
7670                missing_type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7671            );
7672        }
7673        if cur > offset || cur + self.buf.len() < offset {
7674            return (stack, None);
7675        }
7676        let mut attrs = self.clone();
7677        let mut last_off = cur + attrs.pos;
7678        let mut missing = None;
7679        while let Some(attr) = attrs.next() {
7680            let Ok(attr) = attr else { break };
7681            match attr {
7682                OpPagePoolStatsGetDumpReply::Info(val) => {
7683                    (stack, missing) = val.lookup_attr(offset, missing_type);
7684                    if !stack.is_empty() {
7685                        break;
7686                    }
7687                }
7688                OpPagePoolStatsGetDumpReply::AllocFast(val) => {
7689                    if last_off == offset {
7690                        stack.push(("AllocFast", last_off));
7691                        break;
7692                    }
7693                }
7694                OpPagePoolStatsGetDumpReply::AllocSlow(val) => {
7695                    if last_off == offset {
7696                        stack.push(("AllocSlow", last_off));
7697                        break;
7698                    }
7699                }
7700                OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7701                    if last_off == offset {
7702                        stack.push(("AllocSlowHighOrder", last_off));
7703                        break;
7704                    }
7705                }
7706                OpPagePoolStatsGetDumpReply::AllocEmpty(val) => {
7707                    if last_off == offset {
7708                        stack.push(("AllocEmpty", last_off));
7709                        break;
7710                    }
7711                }
7712                OpPagePoolStatsGetDumpReply::AllocRefill(val) => {
7713                    if last_off == offset {
7714                        stack.push(("AllocRefill", last_off));
7715                        break;
7716                    }
7717                }
7718                OpPagePoolStatsGetDumpReply::AllocWaive(val) => {
7719                    if last_off == offset {
7720                        stack.push(("AllocWaive", last_off));
7721                        break;
7722                    }
7723                }
7724                OpPagePoolStatsGetDumpReply::RecycleCached(val) => {
7725                    if last_off == offset {
7726                        stack.push(("RecycleCached", last_off));
7727                        break;
7728                    }
7729                }
7730                OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7731                    if last_off == offset {
7732                        stack.push(("RecycleCacheFull", last_off));
7733                        break;
7734                    }
7735                }
7736                OpPagePoolStatsGetDumpReply::RecycleRing(val) => {
7737                    if last_off == offset {
7738                        stack.push(("RecycleRing", last_off));
7739                        break;
7740                    }
7741                }
7742                OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7743                    if last_off == offset {
7744                        stack.push(("RecycleRingFull", last_off));
7745                        break;
7746                    }
7747                }
7748                OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7749                    if last_off == offset {
7750                        stack.push(("RecycleReleasedRefcnt", last_off));
7751                        break;
7752                    }
7753                }
7754                _ => {}
7755            };
7756            last_off = cur + attrs.pos;
7757        }
7758        if !stack.is_empty() {
7759            stack.push(("OpPagePoolStatsGetDumpReply", cur));
7760        }
7761        (stack, missing)
7762    }
7763}
7764#[derive(Debug)]
7765pub struct RequestOpPagePoolStatsGetDumpRequest<'r> {
7766    request: Request<'r>,
7767}
7768impl<'r> RequestOpPagePoolStatsGetDumpRequest<'r> {
7769    pub fn new(mut request: Request<'r>) -> Self {
7770        PushOpPagePoolStatsGetDumpRequest::write_header(&mut request.buf_mut());
7771        Self {
7772            request: request.set_dump(),
7773        }
7774    }
7775    pub fn encode(&mut self) -> PushOpPagePoolStatsGetDumpRequest<&mut Vec<u8>> {
7776        PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf_mut())
7777    }
7778    pub fn into_encoder(self) -> PushOpPagePoolStatsGetDumpRequest<RequestBuf<'r>> {
7779        PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf)
7780    }
7781}
7782impl NetlinkRequest for RequestOpPagePoolStatsGetDumpRequest<'_> {
7783    type ReplyType<'buf> = IterableOpPagePoolStatsGetDumpReply<'buf>;
7784    fn protocol(&self) -> Protocol {
7785        Protocol::Generic("netdev".as_bytes())
7786    }
7787    fn flags(&self) -> u16 {
7788        self.request.flags
7789    }
7790    fn payload(&self) -> &[u8] {
7791        self.request.buf()
7792    }
7793    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7794        OpPagePoolStatsGetDumpReply::new(buf)
7795    }
7796    fn lookup(
7797        buf: &[u8],
7798        offset: usize,
7799        missing_type: Option<u16>,
7800    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7801        OpPagePoolStatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
7802    }
7803}
7804#[doc = "Get page pool statistics."]
7805pub struct PushOpPagePoolStatsGetDoRequest<Prev: Rec> {
7806    pub(crate) prev: Option<Prev>,
7807    pub(crate) header_offset: Option<usize>,
7808}
7809impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoRequest<Prev> {
7810    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7811        self.prev.as_mut().unwrap().as_rec_mut()
7812    }
7813}
7814impl<Prev: Rec> PushOpPagePoolStatsGetDoRequest<Prev> {
7815    pub fn new(mut prev: Prev) -> Self {
7816        Self::write_header(&mut prev);
7817        Self::new_without_header(prev)
7818    }
7819    fn new_without_header(prev: Prev) -> Self {
7820        Self {
7821            prev: Some(prev),
7822            header_offset: None,
7823        }
7824    }
7825    fn write_header(prev: &mut Prev) {
7826        let mut header = PushBuiltinNfgenmsg::new();
7827        header.set_cmd(9u8);
7828        header.set_version(1u8);
7829        prev.as_rec_mut().extend(header.as_slice());
7830    }
7831    pub fn end_nested(mut self) -> Prev {
7832        let mut prev = self.prev.take().unwrap();
7833        if let Some(header_offset) = &self.header_offset {
7834            finalize_nested_header(prev.as_rec_mut(), *header_offset);
7835        }
7836        prev
7837    }
7838    #[doc = "Page pool identifying information."]
7839    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7840        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7841        PushPagePoolInfo {
7842            prev: Some(self),
7843            header_offset: Some(header_offset),
7844        }
7845    }
7846}
7847impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoRequest<Prev> {
7848    fn drop(&mut self) {
7849        if let Some(prev) = &mut self.prev {
7850            if let Some(header_offset) = &self.header_offset {
7851                finalize_nested_header(prev.as_rec_mut(), *header_offset);
7852            }
7853        }
7854    }
7855}
7856#[doc = "Get page pool statistics."]
7857#[derive(Clone)]
7858pub enum OpPagePoolStatsGetDoRequest<'a> {
7859    #[doc = "Page pool identifying information."]
7860    Info(IterablePagePoolInfo<'a>),
7861}
7862impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7863    #[doc = "Page pool identifying information."]
7864    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7865        let mut iter = self.clone();
7866        iter.pos = 0;
7867        for attr in iter {
7868            if let OpPagePoolStatsGetDoRequest::Info(val) = attr? {
7869                return Ok(val);
7870            }
7871        }
7872        Err(ErrorContext::new_missing(
7873            "OpPagePoolStatsGetDoRequest",
7874            "Info",
7875            self.orig_loc,
7876            self.buf.as_ptr() as usize,
7877        ))
7878    }
7879}
7880impl OpPagePoolStatsGetDoRequest<'_> {
7881    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoRequest<'a> {
7882        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7883        IterableOpPagePoolStatsGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
7884    }
7885    fn attr_from_type(r#type: u16) -> Option<&'static str> {
7886        PagePoolStats::attr_from_type(r#type)
7887    }
7888}
7889#[derive(Clone, Copy, Default)]
7890pub struct IterableOpPagePoolStatsGetDoRequest<'a> {
7891    buf: &'a [u8],
7892    pos: usize,
7893    orig_loc: usize,
7894}
7895impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7896    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7897        Self {
7898            buf,
7899            pos: 0,
7900            orig_loc,
7901        }
7902    }
7903    pub fn get_buf(&self) -> &'a [u8] {
7904        self.buf
7905    }
7906}
7907impl<'a> Iterator for IterableOpPagePoolStatsGetDoRequest<'a> {
7908    type Item = Result<OpPagePoolStatsGetDoRequest<'a>, ErrorContext>;
7909    fn next(&mut self) -> Option<Self::Item> {
7910        if self.buf.len() == self.pos {
7911            return None;
7912        }
7913        let pos = self.pos;
7914        let mut r#type = None;
7915        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7916            r#type = Some(header.r#type);
7917            let res = match header.r#type {
7918                1u16 => OpPagePoolStatsGetDoRequest::Info({
7919                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7920                    let Some(val) = res else { break };
7921                    val
7922                }),
7923                n => {
7924                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
7925                        break;
7926                    } else {
7927                        continue;
7928                    }
7929                }
7930            };
7931            return Some(Ok(res));
7932        }
7933        Some(Err(ErrorContext::new(
7934            "OpPagePoolStatsGetDoRequest",
7935            r#type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7936            self.orig_loc,
7937            self.buf.as_ptr().wrapping_add(pos) as usize,
7938        )))
7939    }
7940}
7941impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoRequest<'_> {
7942    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7943        let mut fmt = f.debug_struct("OpPagePoolStatsGetDoRequest");
7944        for attr in self.clone() {
7945            let attr = match attr {
7946                Ok(a) => a,
7947                Err(err) => {
7948                    fmt.finish()?;
7949                    f.write_str("Err(")?;
7950                    err.fmt(f)?;
7951                    return f.write_str(")");
7952                }
7953            };
7954            match attr {
7955                OpPagePoolStatsGetDoRequest::Info(val) => fmt.field("Info", &val),
7956            };
7957        }
7958        fmt.finish()
7959    }
7960}
7961impl IterableOpPagePoolStatsGetDoRequest<'_> {
7962    pub fn lookup_attr(
7963        &self,
7964        offset: usize,
7965        missing_type: Option<u16>,
7966    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7967        let mut stack = Vec::new();
7968        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7969        if cur == offset + PushBuiltinNfgenmsg::len() {
7970            stack.push(("OpPagePoolStatsGetDoRequest", offset));
7971            return (
7972                stack,
7973                missing_type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7974            );
7975        }
7976        if cur > offset || cur + self.buf.len() < offset {
7977            return (stack, None);
7978        }
7979        let mut attrs = self.clone();
7980        let mut last_off = cur + attrs.pos;
7981        let mut missing = None;
7982        while let Some(attr) = attrs.next() {
7983            let Ok(attr) = attr else { break };
7984            match attr {
7985                OpPagePoolStatsGetDoRequest::Info(val) => {
7986                    (stack, missing) = val.lookup_attr(offset, missing_type);
7987                    if !stack.is_empty() {
7988                        break;
7989                    }
7990                }
7991                _ => {}
7992            };
7993            last_off = cur + attrs.pos;
7994        }
7995        if !stack.is_empty() {
7996            stack.push(("OpPagePoolStatsGetDoRequest", cur));
7997        }
7998        (stack, missing)
7999    }
8000}
8001#[doc = "Get page pool statistics."]
8002pub struct PushOpPagePoolStatsGetDoReply<Prev: Rec> {
8003    pub(crate) prev: Option<Prev>,
8004    pub(crate) header_offset: Option<usize>,
8005}
8006impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoReply<Prev> {
8007    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8008        self.prev.as_mut().unwrap().as_rec_mut()
8009    }
8010}
8011impl<Prev: Rec> PushOpPagePoolStatsGetDoReply<Prev> {
8012    pub fn new(mut prev: Prev) -> Self {
8013        Self::write_header(&mut prev);
8014        Self::new_without_header(prev)
8015    }
8016    fn new_without_header(prev: Prev) -> Self {
8017        Self {
8018            prev: Some(prev),
8019            header_offset: None,
8020        }
8021    }
8022    fn write_header(prev: &mut Prev) {
8023        let mut header = PushBuiltinNfgenmsg::new();
8024        header.set_cmd(9u8);
8025        header.set_version(1u8);
8026        prev.as_rec_mut().extend(header.as_slice());
8027    }
8028    pub fn end_nested(mut self) -> Prev {
8029        let mut prev = self.prev.take().unwrap();
8030        if let Some(header_offset) = &self.header_offset {
8031            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8032        }
8033        prev
8034    }
8035    #[doc = "Page pool identifying information."]
8036    pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
8037        let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
8038        PushPagePoolInfo {
8039            prev: Some(self),
8040            header_offset: Some(header_offset),
8041        }
8042    }
8043    pub fn push_alloc_fast(mut self, value: u32) -> Self {
8044        push_header(self.as_rec_mut(), 8u16, 4 as u16);
8045        self.as_rec_mut().extend(value.to_ne_bytes());
8046        self
8047    }
8048    pub fn push_alloc_slow(mut self, value: u32) -> Self {
8049        push_header(self.as_rec_mut(), 9u16, 4 as u16);
8050        self.as_rec_mut().extend(value.to_ne_bytes());
8051        self
8052    }
8053    pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
8054        push_header(self.as_rec_mut(), 10u16, 4 as u16);
8055        self.as_rec_mut().extend(value.to_ne_bytes());
8056        self
8057    }
8058    pub fn push_alloc_empty(mut self, value: u32) -> Self {
8059        push_header(self.as_rec_mut(), 11u16, 4 as u16);
8060        self.as_rec_mut().extend(value.to_ne_bytes());
8061        self
8062    }
8063    pub fn push_alloc_refill(mut self, value: u32) -> Self {
8064        push_header(self.as_rec_mut(), 12u16, 4 as u16);
8065        self.as_rec_mut().extend(value.to_ne_bytes());
8066        self
8067    }
8068    pub fn push_alloc_waive(mut self, value: u32) -> Self {
8069        push_header(self.as_rec_mut(), 13u16, 4 as u16);
8070        self.as_rec_mut().extend(value.to_ne_bytes());
8071        self
8072    }
8073    pub fn push_recycle_cached(mut self, value: u32) -> Self {
8074        push_header(self.as_rec_mut(), 14u16, 4 as u16);
8075        self.as_rec_mut().extend(value.to_ne_bytes());
8076        self
8077    }
8078    pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
8079        push_header(self.as_rec_mut(), 15u16, 4 as u16);
8080        self.as_rec_mut().extend(value.to_ne_bytes());
8081        self
8082    }
8083    pub fn push_recycle_ring(mut self, value: u32) -> Self {
8084        push_header(self.as_rec_mut(), 16u16, 4 as u16);
8085        self.as_rec_mut().extend(value.to_ne_bytes());
8086        self
8087    }
8088    pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
8089        push_header(self.as_rec_mut(), 17u16, 4 as u16);
8090        self.as_rec_mut().extend(value.to_ne_bytes());
8091        self
8092    }
8093    pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
8094        push_header(self.as_rec_mut(), 18u16, 4 as u16);
8095        self.as_rec_mut().extend(value.to_ne_bytes());
8096        self
8097    }
8098}
8099impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoReply<Prev> {
8100    fn drop(&mut self) {
8101        if let Some(prev) = &mut self.prev {
8102            if let Some(header_offset) = &self.header_offset {
8103                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8104            }
8105        }
8106    }
8107}
8108#[doc = "Get page pool statistics."]
8109#[derive(Clone)]
8110pub enum OpPagePoolStatsGetDoReply<'a> {
8111    #[doc = "Page pool identifying information."]
8112    Info(IterablePagePoolInfo<'a>),
8113    AllocFast(u32),
8114    AllocSlow(u32),
8115    AllocSlowHighOrder(u32),
8116    AllocEmpty(u32),
8117    AllocRefill(u32),
8118    AllocWaive(u32),
8119    RecycleCached(u32),
8120    RecycleCacheFull(u32),
8121    RecycleRing(u32),
8122    RecycleRingFull(u32),
8123    RecycleReleasedRefcnt(u32),
8124}
8125impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8126    #[doc = "Page pool identifying information."]
8127    pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
8128        let mut iter = self.clone();
8129        iter.pos = 0;
8130        for attr in iter {
8131            if let OpPagePoolStatsGetDoReply::Info(val) = attr? {
8132                return Ok(val);
8133            }
8134        }
8135        Err(ErrorContext::new_missing(
8136            "OpPagePoolStatsGetDoReply",
8137            "Info",
8138            self.orig_loc,
8139            self.buf.as_ptr() as usize,
8140        ))
8141    }
8142    pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
8143        let mut iter = self.clone();
8144        iter.pos = 0;
8145        for attr in iter {
8146            if let OpPagePoolStatsGetDoReply::AllocFast(val) = attr? {
8147                return Ok(val);
8148            }
8149        }
8150        Err(ErrorContext::new_missing(
8151            "OpPagePoolStatsGetDoReply",
8152            "AllocFast",
8153            self.orig_loc,
8154            self.buf.as_ptr() as usize,
8155        ))
8156    }
8157    pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
8158        let mut iter = self.clone();
8159        iter.pos = 0;
8160        for attr in iter {
8161            if let OpPagePoolStatsGetDoReply::AllocSlow(val) = attr? {
8162                return Ok(val);
8163            }
8164        }
8165        Err(ErrorContext::new_missing(
8166            "OpPagePoolStatsGetDoReply",
8167            "AllocSlow",
8168            self.orig_loc,
8169            self.buf.as_ptr() as usize,
8170        ))
8171    }
8172    pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
8173        let mut iter = self.clone();
8174        iter.pos = 0;
8175        for attr in iter {
8176            if let OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) = attr? {
8177                return Ok(val);
8178            }
8179        }
8180        Err(ErrorContext::new_missing(
8181            "OpPagePoolStatsGetDoReply",
8182            "AllocSlowHighOrder",
8183            self.orig_loc,
8184            self.buf.as_ptr() as usize,
8185        ))
8186    }
8187    pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
8188        let mut iter = self.clone();
8189        iter.pos = 0;
8190        for attr in iter {
8191            if let OpPagePoolStatsGetDoReply::AllocEmpty(val) = attr? {
8192                return Ok(val);
8193            }
8194        }
8195        Err(ErrorContext::new_missing(
8196            "OpPagePoolStatsGetDoReply",
8197            "AllocEmpty",
8198            self.orig_loc,
8199            self.buf.as_ptr() as usize,
8200        ))
8201    }
8202    pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
8203        let mut iter = self.clone();
8204        iter.pos = 0;
8205        for attr in iter {
8206            if let OpPagePoolStatsGetDoReply::AllocRefill(val) = attr? {
8207                return Ok(val);
8208            }
8209        }
8210        Err(ErrorContext::new_missing(
8211            "OpPagePoolStatsGetDoReply",
8212            "AllocRefill",
8213            self.orig_loc,
8214            self.buf.as_ptr() as usize,
8215        ))
8216    }
8217    pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
8218        let mut iter = self.clone();
8219        iter.pos = 0;
8220        for attr in iter {
8221            if let OpPagePoolStatsGetDoReply::AllocWaive(val) = attr? {
8222                return Ok(val);
8223            }
8224        }
8225        Err(ErrorContext::new_missing(
8226            "OpPagePoolStatsGetDoReply",
8227            "AllocWaive",
8228            self.orig_loc,
8229            self.buf.as_ptr() as usize,
8230        ))
8231    }
8232    pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
8233        let mut iter = self.clone();
8234        iter.pos = 0;
8235        for attr in iter {
8236            if let OpPagePoolStatsGetDoReply::RecycleCached(val) = attr? {
8237                return Ok(val);
8238            }
8239        }
8240        Err(ErrorContext::new_missing(
8241            "OpPagePoolStatsGetDoReply",
8242            "RecycleCached",
8243            self.orig_loc,
8244            self.buf.as_ptr() as usize,
8245        ))
8246    }
8247    pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
8248        let mut iter = self.clone();
8249        iter.pos = 0;
8250        for attr in iter {
8251            if let OpPagePoolStatsGetDoReply::RecycleCacheFull(val) = attr? {
8252                return Ok(val);
8253            }
8254        }
8255        Err(ErrorContext::new_missing(
8256            "OpPagePoolStatsGetDoReply",
8257            "RecycleCacheFull",
8258            self.orig_loc,
8259            self.buf.as_ptr() as usize,
8260        ))
8261    }
8262    pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
8263        let mut iter = self.clone();
8264        iter.pos = 0;
8265        for attr in iter {
8266            if let OpPagePoolStatsGetDoReply::RecycleRing(val) = attr? {
8267                return Ok(val);
8268            }
8269        }
8270        Err(ErrorContext::new_missing(
8271            "OpPagePoolStatsGetDoReply",
8272            "RecycleRing",
8273            self.orig_loc,
8274            self.buf.as_ptr() as usize,
8275        ))
8276    }
8277    pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
8278        let mut iter = self.clone();
8279        iter.pos = 0;
8280        for attr in iter {
8281            if let OpPagePoolStatsGetDoReply::RecycleRingFull(val) = attr? {
8282                return Ok(val);
8283            }
8284        }
8285        Err(ErrorContext::new_missing(
8286            "OpPagePoolStatsGetDoReply",
8287            "RecycleRingFull",
8288            self.orig_loc,
8289            self.buf.as_ptr() as usize,
8290        ))
8291    }
8292    pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
8293        let mut iter = self.clone();
8294        iter.pos = 0;
8295        for attr in iter {
8296            if let OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) = attr? {
8297                return Ok(val);
8298            }
8299        }
8300        Err(ErrorContext::new_missing(
8301            "OpPagePoolStatsGetDoReply",
8302            "RecycleReleasedRefcnt",
8303            self.orig_loc,
8304            self.buf.as_ptr() as usize,
8305        ))
8306    }
8307}
8308impl OpPagePoolStatsGetDoReply<'_> {
8309    pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoReply<'a> {
8310        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8311        IterableOpPagePoolStatsGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
8312    }
8313    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8314        PagePoolStats::attr_from_type(r#type)
8315    }
8316}
8317#[derive(Clone, Copy, Default)]
8318pub struct IterableOpPagePoolStatsGetDoReply<'a> {
8319    buf: &'a [u8],
8320    pos: usize,
8321    orig_loc: usize,
8322}
8323impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8324    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8325        Self {
8326            buf,
8327            pos: 0,
8328            orig_loc,
8329        }
8330    }
8331    pub fn get_buf(&self) -> &'a [u8] {
8332        self.buf
8333    }
8334}
8335impl<'a> Iterator for IterableOpPagePoolStatsGetDoReply<'a> {
8336    type Item = Result<OpPagePoolStatsGetDoReply<'a>, ErrorContext>;
8337    fn next(&mut self) -> Option<Self::Item> {
8338        if self.buf.len() == self.pos {
8339            return None;
8340        }
8341        let pos = self.pos;
8342        let mut r#type = None;
8343        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
8344            r#type = Some(header.r#type);
8345            let res = match header.r#type {
8346                1u16 => OpPagePoolStatsGetDoReply::Info({
8347                    let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
8348                    let Some(val) = res else { break };
8349                    val
8350                }),
8351                8u16 => OpPagePoolStatsGetDoReply::AllocFast({
8352                    let res = parse_u32(next);
8353                    let Some(val) = res else { break };
8354                    val
8355                }),
8356                9u16 => OpPagePoolStatsGetDoReply::AllocSlow({
8357                    let res = parse_u32(next);
8358                    let Some(val) = res else { break };
8359                    val
8360                }),
8361                10u16 => OpPagePoolStatsGetDoReply::AllocSlowHighOrder({
8362                    let res = parse_u32(next);
8363                    let Some(val) = res else { break };
8364                    val
8365                }),
8366                11u16 => OpPagePoolStatsGetDoReply::AllocEmpty({
8367                    let res = parse_u32(next);
8368                    let Some(val) = res else { break };
8369                    val
8370                }),
8371                12u16 => OpPagePoolStatsGetDoReply::AllocRefill({
8372                    let res = parse_u32(next);
8373                    let Some(val) = res else { break };
8374                    val
8375                }),
8376                13u16 => OpPagePoolStatsGetDoReply::AllocWaive({
8377                    let res = parse_u32(next);
8378                    let Some(val) = res else { break };
8379                    val
8380                }),
8381                14u16 => OpPagePoolStatsGetDoReply::RecycleCached({
8382                    let res = parse_u32(next);
8383                    let Some(val) = res else { break };
8384                    val
8385                }),
8386                15u16 => OpPagePoolStatsGetDoReply::RecycleCacheFull({
8387                    let res = parse_u32(next);
8388                    let Some(val) = res else { break };
8389                    val
8390                }),
8391                16u16 => OpPagePoolStatsGetDoReply::RecycleRing({
8392                    let res = parse_u32(next);
8393                    let Some(val) = res else { break };
8394                    val
8395                }),
8396                17u16 => OpPagePoolStatsGetDoReply::RecycleRingFull({
8397                    let res = parse_u32(next);
8398                    let Some(val) = res else { break };
8399                    val
8400                }),
8401                18u16 => OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt({
8402                    let res = parse_u32(next);
8403                    let Some(val) = res else { break };
8404                    val
8405                }),
8406                n => {
8407                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
8408                        break;
8409                    } else {
8410                        continue;
8411                    }
8412                }
8413            };
8414            return Some(Ok(res));
8415        }
8416        Some(Err(ErrorContext::new(
8417            "OpPagePoolStatsGetDoReply",
8418            r#type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8419            self.orig_loc,
8420            self.buf.as_ptr().wrapping_add(pos) as usize,
8421        )))
8422    }
8423}
8424impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoReply<'_> {
8425    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8426        let mut fmt = f.debug_struct("OpPagePoolStatsGetDoReply");
8427        for attr in self.clone() {
8428            let attr = match attr {
8429                Ok(a) => a,
8430                Err(err) => {
8431                    fmt.finish()?;
8432                    f.write_str("Err(")?;
8433                    err.fmt(f)?;
8434                    return f.write_str(")");
8435                }
8436            };
8437            match attr {
8438                OpPagePoolStatsGetDoReply::Info(val) => fmt.field("Info", &val),
8439                OpPagePoolStatsGetDoReply::AllocFast(val) => fmt.field("AllocFast", &val),
8440                OpPagePoolStatsGetDoReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
8441                OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8442                    fmt.field("AllocSlowHighOrder", &val)
8443                }
8444                OpPagePoolStatsGetDoReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
8445                OpPagePoolStatsGetDoReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
8446                OpPagePoolStatsGetDoReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
8447                OpPagePoolStatsGetDoReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
8448                OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8449                    fmt.field("RecycleCacheFull", &val)
8450                }
8451                OpPagePoolStatsGetDoReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
8452                OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8453                    fmt.field("RecycleRingFull", &val)
8454                }
8455                OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8456                    fmt.field("RecycleReleasedRefcnt", &val)
8457                }
8458            };
8459        }
8460        fmt.finish()
8461    }
8462}
8463impl IterableOpPagePoolStatsGetDoReply<'_> {
8464    pub fn lookup_attr(
8465        &self,
8466        offset: usize,
8467        missing_type: Option<u16>,
8468    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8469        let mut stack = Vec::new();
8470        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8471        if cur == offset + PushBuiltinNfgenmsg::len() {
8472            stack.push(("OpPagePoolStatsGetDoReply", offset));
8473            return (
8474                stack,
8475                missing_type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8476            );
8477        }
8478        if cur > offset || cur + self.buf.len() < offset {
8479            return (stack, None);
8480        }
8481        let mut attrs = self.clone();
8482        let mut last_off = cur + attrs.pos;
8483        let mut missing = None;
8484        while let Some(attr) = attrs.next() {
8485            let Ok(attr) = attr else { break };
8486            match attr {
8487                OpPagePoolStatsGetDoReply::Info(val) => {
8488                    (stack, missing) = val.lookup_attr(offset, missing_type);
8489                    if !stack.is_empty() {
8490                        break;
8491                    }
8492                }
8493                OpPagePoolStatsGetDoReply::AllocFast(val) => {
8494                    if last_off == offset {
8495                        stack.push(("AllocFast", last_off));
8496                        break;
8497                    }
8498                }
8499                OpPagePoolStatsGetDoReply::AllocSlow(val) => {
8500                    if last_off == offset {
8501                        stack.push(("AllocSlow", last_off));
8502                        break;
8503                    }
8504                }
8505                OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8506                    if last_off == offset {
8507                        stack.push(("AllocSlowHighOrder", last_off));
8508                        break;
8509                    }
8510                }
8511                OpPagePoolStatsGetDoReply::AllocEmpty(val) => {
8512                    if last_off == offset {
8513                        stack.push(("AllocEmpty", last_off));
8514                        break;
8515                    }
8516                }
8517                OpPagePoolStatsGetDoReply::AllocRefill(val) => {
8518                    if last_off == offset {
8519                        stack.push(("AllocRefill", last_off));
8520                        break;
8521                    }
8522                }
8523                OpPagePoolStatsGetDoReply::AllocWaive(val) => {
8524                    if last_off == offset {
8525                        stack.push(("AllocWaive", last_off));
8526                        break;
8527                    }
8528                }
8529                OpPagePoolStatsGetDoReply::RecycleCached(val) => {
8530                    if last_off == offset {
8531                        stack.push(("RecycleCached", last_off));
8532                        break;
8533                    }
8534                }
8535                OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8536                    if last_off == offset {
8537                        stack.push(("RecycleCacheFull", last_off));
8538                        break;
8539                    }
8540                }
8541                OpPagePoolStatsGetDoReply::RecycleRing(val) => {
8542                    if last_off == offset {
8543                        stack.push(("RecycleRing", last_off));
8544                        break;
8545                    }
8546                }
8547                OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8548                    if last_off == offset {
8549                        stack.push(("RecycleRingFull", last_off));
8550                        break;
8551                    }
8552                }
8553                OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8554                    if last_off == offset {
8555                        stack.push(("RecycleReleasedRefcnt", last_off));
8556                        break;
8557                    }
8558                }
8559                _ => {}
8560            };
8561            last_off = cur + attrs.pos;
8562        }
8563        if !stack.is_empty() {
8564            stack.push(("OpPagePoolStatsGetDoReply", cur));
8565        }
8566        (stack, missing)
8567    }
8568}
8569#[derive(Debug)]
8570pub struct RequestOpPagePoolStatsGetDoRequest<'r> {
8571    request: Request<'r>,
8572}
8573impl<'r> RequestOpPagePoolStatsGetDoRequest<'r> {
8574    pub fn new(mut request: Request<'r>) -> Self {
8575        PushOpPagePoolStatsGetDoRequest::write_header(&mut request.buf_mut());
8576        Self { request: request }
8577    }
8578    pub fn encode(&mut self) -> PushOpPagePoolStatsGetDoRequest<&mut Vec<u8>> {
8579        PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf_mut())
8580    }
8581    pub fn into_encoder(self) -> PushOpPagePoolStatsGetDoRequest<RequestBuf<'r>> {
8582        PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf)
8583    }
8584}
8585impl NetlinkRequest for RequestOpPagePoolStatsGetDoRequest<'_> {
8586    type ReplyType<'buf> = IterableOpPagePoolStatsGetDoReply<'buf>;
8587    fn protocol(&self) -> Protocol {
8588        Protocol::Generic("netdev".as_bytes())
8589    }
8590    fn flags(&self) -> u16 {
8591        self.request.flags
8592    }
8593    fn payload(&self) -> &[u8] {
8594        self.request.buf()
8595    }
8596    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8597        OpPagePoolStatsGetDoReply::new(buf)
8598    }
8599    fn lookup(
8600        buf: &[u8],
8601        offset: usize,
8602        missing_type: Option<u16>,
8603    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8604        OpPagePoolStatsGetDoRequest::new(buf).lookup_attr(offset, missing_type)
8605    }
8606}
8607#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8608pub struct PushOpQueueGetDumpRequest<Prev: Rec> {
8609    pub(crate) prev: Option<Prev>,
8610    pub(crate) header_offset: Option<usize>,
8611}
8612impl<Prev: Rec> Rec for PushOpQueueGetDumpRequest<Prev> {
8613    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8614        self.prev.as_mut().unwrap().as_rec_mut()
8615    }
8616}
8617impl<Prev: Rec> PushOpQueueGetDumpRequest<Prev> {
8618    pub fn new(mut prev: Prev) -> Self {
8619        Self::write_header(&mut prev);
8620        Self::new_without_header(prev)
8621    }
8622    fn new_without_header(prev: Prev) -> Self {
8623        Self {
8624            prev: Some(prev),
8625            header_offset: None,
8626        }
8627    }
8628    fn write_header(prev: &mut Prev) {
8629        let mut header = PushBuiltinNfgenmsg::new();
8630        header.set_cmd(10u8);
8631        header.set_version(1u8);
8632        prev.as_rec_mut().extend(header.as_slice());
8633    }
8634    pub fn end_nested(mut self) -> Prev {
8635        let mut prev = self.prev.take().unwrap();
8636        if let Some(header_offset) = &self.header_offset {
8637            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8638        }
8639        prev
8640    }
8641    #[doc = "ifindex of the netdevice to which the queue belongs."]
8642    pub fn push_ifindex(mut self, value: u32) -> Self {
8643        push_header(self.as_rec_mut(), 2u16, 4 as u16);
8644        self.as_rec_mut().extend(value.to_ne_bytes());
8645        self
8646    }
8647}
8648impl<Prev: Rec> Drop for PushOpQueueGetDumpRequest<Prev> {
8649    fn drop(&mut self) {
8650        if let Some(prev) = &mut self.prev {
8651            if let Some(header_offset) = &self.header_offset {
8652                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8653            }
8654        }
8655    }
8656}
8657#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8658#[derive(Clone)]
8659pub enum OpQueueGetDumpRequest {
8660    #[doc = "ifindex of the netdevice to which the queue belongs."]
8661    Ifindex(u32),
8662}
8663impl<'a> IterableOpQueueGetDumpRequest<'a> {
8664    #[doc = "ifindex of the netdevice to which the queue belongs."]
8665    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8666        let mut iter = self.clone();
8667        iter.pos = 0;
8668        for attr in iter {
8669            if let OpQueueGetDumpRequest::Ifindex(val) = attr? {
8670                return Ok(val);
8671            }
8672        }
8673        Err(ErrorContext::new_missing(
8674            "OpQueueGetDumpRequest",
8675            "Ifindex",
8676            self.orig_loc,
8677            self.buf.as_ptr() as usize,
8678        ))
8679    }
8680}
8681impl OpQueueGetDumpRequest {
8682    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpRequest<'a> {
8683        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8684        IterableOpQueueGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
8685    }
8686    fn attr_from_type(r#type: u16) -> Option<&'static str> {
8687        Queue::attr_from_type(r#type)
8688    }
8689}
8690#[derive(Clone, Copy, Default)]
8691pub struct IterableOpQueueGetDumpRequest<'a> {
8692    buf: &'a [u8],
8693    pos: usize,
8694    orig_loc: usize,
8695}
8696impl<'a> IterableOpQueueGetDumpRequest<'a> {
8697    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8698        Self {
8699            buf,
8700            pos: 0,
8701            orig_loc,
8702        }
8703    }
8704    pub fn get_buf(&self) -> &'a [u8] {
8705        self.buf
8706    }
8707}
8708impl<'a> Iterator for IterableOpQueueGetDumpRequest<'a> {
8709    type Item = Result<OpQueueGetDumpRequest, ErrorContext>;
8710    fn next(&mut self) -> Option<Self::Item> {
8711        if self.buf.len() == self.pos {
8712            return None;
8713        }
8714        let pos = self.pos;
8715        let mut r#type = None;
8716        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
8717            r#type = Some(header.r#type);
8718            let res = match header.r#type {
8719                2u16 => OpQueueGetDumpRequest::Ifindex({
8720                    let res = parse_u32(next);
8721                    let Some(val) = res else { break };
8722                    val
8723                }),
8724                n => {
8725                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
8726                        break;
8727                    } else {
8728                        continue;
8729                    }
8730                }
8731            };
8732            return Some(Ok(res));
8733        }
8734        Some(Err(ErrorContext::new(
8735            "OpQueueGetDumpRequest",
8736            r#type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8737            self.orig_loc,
8738            self.buf.as_ptr().wrapping_add(pos) as usize,
8739        )))
8740    }
8741}
8742impl std::fmt::Debug for IterableOpQueueGetDumpRequest<'_> {
8743    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8744        let mut fmt = f.debug_struct("OpQueueGetDumpRequest");
8745        for attr in self.clone() {
8746            let attr = match attr {
8747                Ok(a) => a,
8748                Err(err) => {
8749                    fmt.finish()?;
8750                    f.write_str("Err(")?;
8751                    err.fmt(f)?;
8752                    return f.write_str(")");
8753                }
8754            };
8755            match attr {
8756                OpQueueGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
8757            };
8758        }
8759        fmt.finish()
8760    }
8761}
8762impl IterableOpQueueGetDumpRequest<'_> {
8763    pub fn lookup_attr(
8764        &self,
8765        offset: usize,
8766        missing_type: Option<u16>,
8767    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8768        let mut stack = Vec::new();
8769        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8770        if cur == offset + PushBuiltinNfgenmsg::len() {
8771            stack.push(("OpQueueGetDumpRequest", offset));
8772            return (
8773                stack,
8774                missing_type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8775            );
8776        }
8777        if cur > offset || cur + self.buf.len() < offset {
8778            return (stack, None);
8779        }
8780        let mut attrs = self.clone();
8781        let mut last_off = cur + attrs.pos;
8782        while let Some(attr) = attrs.next() {
8783            let Ok(attr) = attr else { break };
8784            match attr {
8785                OpQueueGetDumpRequest::Ifindex(val) => {
8786                    if last_off == offset {
8787                        stack.push(("Ifindex", last_off));
8788                        break;
8789                    }
8790                }
8791                _ => {}
8792            };
8793            last_off = cur + attrs.pos;
8794        }
8795        if !stack.is_empty() {
8796            stack.push(("OpQueueGetDumpRequest", cur));
8797        }
8798        (stack, None)
8799    }
8800}
8801#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8802pub struct PushOpQueueGetDumpReply<Prev: Rec> {
8803    pub(crate) prev: Option<Prev>,
8804    pub(crate) header_offset: Option<usize>,
8805}
8806impl<Prev: Rec> Rec for PushOpQueueGetDumpReply<Prev> {
8807    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8808        self.prev.as_mut().unwrap().as_rec_mut()
8809    }
8810}
8811impl<Prev: Rec> PushOpQueueGetDumpReply<Prev> {
8812    pub fn new(mut prev: Prev) -> Self {
8813        Self::write_header(&mut prev);
8814        Self::new_without_header(prev)
8815    }
8816    fn new_without_header(prev: Prev) -> Self {
8817        Self {
8818            prev: Some(prev),
8819            header_offset: None,
8820        }
8821    }
8822    fn write_header(prev: &mut Prev) {
8823        let mut header = PushBuiltinNfgenmsg::new();
8824        header.set_cmd(10u8);
8825        header.set_version(1u8);
8826        prev.as_rec_mut().extend(header.as_slice());
8827    }
8828    pub fn end_nested(mut self) -> Prev {
8829        let mut prev = self.prev.take().unwrap();
8830        if let Some(header_offset) = &self.header_offset {
8831            finalize_nested_header(prev.as_rec_mut(), *header_offset);
8832        }
8833        prev
8834    }
8835    #[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."]
8836    pub fn push_id(mut self, value: u32) -> Self {
8837        push_header(self.as_rec_mut(), 1u16, 4 as u16);
8838        self.as_rec_mut().extend(value.to_ne_bytes());
8839        self
8840    }
8841    #[doc = "ifindex of the netdevice to which the queue belongs."]
8842    pub fn push_ifindex(mut self, value: u32) -> Self {
8843        push_header(self.as_rec_mut(), 2u16, 4 as u16);
8844        self.as_rec_mut().extend(value.to_ne_bytes());
8845        self
8846    }
8847    #[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)"]
8848    pub fn push_type(mut self, value: u32) -> Self {
8849        push_header(self.as_rec_mut(), 3u16, 4 as u16);
8850        self.as_rec_mut().extend(value.to_ne_bytes());
8851        self
8852    }
8853    #[doc = "ID of the NAPI instance which services this queue."]
8854    pub fn push_napi_id(mut self, value: u32) -> Self {
8855        push_header(self.as_rec_mut(), 4u16, 4 as u16);
8856        self.as_rec_mut().extend(value.to_ne_bytes());
8857        self
8858    }
8859    #[doc = "ID of the dmabuf attached to this queue, if any."]
8860    pub fn push_dmabuf(mut self, value: u32) -> Self {
8861        push_header(self.as_rec_mut(), 5u16, 4 as u16);
8862        self.as_rec_mut().extend(value.to_ne_bytes());
8863        self
8864    }
8865    #[doc = "io_uring memory provider information."]
8866    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
8867        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
8868        PushIoUringProviderInfo {
8869            prev: Some(self),
8870            header_offset: Some(header_offset),
8871        }
8872    }
8873    #[doc = "XSK information for this queue, if any."]
8874    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
8875        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
8876        PushXskInfo {
8877            prev: Some(self),
8878            header_offset: Some(header_offset),
8879        }
8880    }
8881}
8882impl<Prev: Rec> Drop for PushOpQueueGetDumpReply<Prev> {
8883    fn drop(&mut self) {
8884        if let Some(prev) = &mut self.prev {
8885            if let Some(header_offset) = &self.header_offset {
8886                finalize_nested_header(prev.as_rec_mut(), *header_offset);
8887            }
8888        }
8889    }
8890}
8891#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8892#[derive(Clone)]
8893pub enum OpQueueGetDumpReply<'a> {
8894    #[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."]
8895    Id(u32),
8896    #[doc = "ifindex of the netdevice to which the queue belongs."]
8897    Ifindex(u32),
8898    #[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)"]
8899    Type(u32),
8900    #[doc = "ID of the NAPI instance which services this queue."]
8901    NapiId(u32),
8902    #[doc = "ID of the dmabuf attached to this queue, if any."]
8903    Dmabuf(u32),
8904    #[doc = "io_uring memory provider information."]
8905    IoUring(IterableIoUringProviderInfo<'a>),
8906    #[doc = "XSK information for this queue, if any."]
8907    Xsk(IterableXskInfo<'a>),
8908}
8909impl<'a> IterableOpQueueGetDumpReply<'a> {
8910    #[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."]
8911    pub fn get_id(&self) -> Result<u32, ErrorContext> {
8912        let mut iter = self.clone();
8913        iter.pos = 0;
8914        for attr in iter {
8915            if let OpQueueGetDumpReply::Id(val) = attr? {
8916                return Ok(val);
8917            }
8918        }
8919        Err(ErrorContext::new_missing(
8920            "OpQueueGetDumpReply",
8921            "Id",
8922            self.orig_loc,
8923            self.buf.as_ptr() as usize,
8924        ))
8925    }
8926    #[doc = "ifindex of the netdevice to which the queue belongs."]
8927    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8928        let mut iter = self.clone();
8929        iter.pos = 0;
8930        for attr in iter {
8931            if let OpQueueGetDumpReply::Ifindex(val) = attr? {
8932                return Ok(val);
8933            }
8934        }
8935        Err(ErrorContext::new_missing(
8936            "OpQueueGetDumpReply",
8937            "Ifindex",
8938            self.orig_loc,
8939            self.buf.as_ptr() as usize,
8940        ))
8941    }
8942    #[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)"]
8943    pub fn get_type(&self) -> Result<u32, ErrorContext> {
8944        let mut iter = self.clone();
8945        iter.pos = 0;
8946        for attr in iter {
8947            if let OpQueueGetDumpReply::Type(val) = attr? {
8948                return Ok(val);
8949            }
8950        }
8951        Err(ErrorContext::new_missing(
8952            "OpQueueGetDumpReply",
8953            "Type",
8954            self.orig_loc,
8955            self.buf.as_ptr() as usize,
8956        ))
8957    }
8958    #[doc = "ID of the NAPI instance which services this queue."]
8959    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
8960        let mut iter = self.clone();
8961        iter.pos = 0;
8962        for attr in iter {
8963            if let OpQueueGetDumpReply::NapiId(val) = attr? {
8964                return Ok(val);
8965            }
8966        }
8967        Err(ErrorContext::new_missing(
8968            "OpQueueGetDumpReply",
8969            "NapiId",
8970            self.orig_loc,
8971            self.buf.as_ptr() as usize,
8972        ))
8973    }
8974    #[doc = "ID of the dmabuf attached to this queue, if any."]
8975    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
8976        let mut iter = self.clone();
8977        iter.pos = 0;
8978        for attr in iter {
8979            if let OpQueueGetDumpReply::Dmabuf(val) = attr? {
8980                return Ok(val);
8981            }
8982        }
8983        Err(ErrorContext::new_missing(
8984            "OpQueueGetDumpReply",
8985            "Dmabuf",
8986            self.orig_loc,
8987            self.buf.as_ptr() as usize,
8988        ))
8989    }
8990    #[doc = "io_uring memory provider information."]
8991    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
8992        let mut iter = self.clone();
8993        iter.pos = 0;
8994        for attr in iter {
8995            if let OpQueueGetDumpReply::IoUring(val) = attr? {
8996                return Ok(val);
8997            }
8998        }
8999        Err(ErrorContext::new_missing(
9000            "OpQueueGetDumpReply",
9001            "IoUring",
9002            self.orig_loc,
9003            self.buf.as_ptr() as usize,
9004        ))
9005    }
9006    #[doc = "XSK information for this queue, if any."]
9007    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9008        let mut iter = self.clone();
9009        iter.pos = 0;
9010        for attr in iter {
9011            if let OpQueueGetDumpReply::Xsk(val) = attr? {
9012                return Ok(val);
9013            }
9014        }
9015        Err(ErrorContext::new_missing(
9016            "OpQueueGetDumpReply",
9017            "Xsk",
9018            self.orig_loc,
9019            self.buf.as_ptr() as usize,
9020        ))
9021    }
9022}
9023impl OpQueueGetDumpReply<'_> {
9024    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpReply<'a> {
9025        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9026        IterableOpQueueGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
9027    }
9028    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9029        Queue::attr_from_type(r#type)
9030    }
9031}
9032#[derive(Clone, Copy, Default)]
9033pub struct IterableOpQueueGetDumpReply<'a> {
9034    buf: &'a [u8],
9035    pos: usize,
9036    orig_loc: usize,
9037}
9038impl<'a> IterableOpQueueGetDumpReply<'a> {
9039    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9040        Self {
9041            buf,
9042            pos: 0,
9043            orig_loc,
9044        }
9045    }
9046    pub fn get_buf(&self) -> &'a [u8] {
9047        self.buf
9048    }
9049}
9050impl<'a> Iterator for IterableOpQueueGetDumpReply<'a> {
9051    type Item = Result<OpQueueGetDumpReply<'a>, ErrorContext>;
9052    fn next(&mut self) -> Option<Self::Item> {
9053        if self.buf.len() == self.pos {
9054            return None;
9055        }
9056        let pos = self.pos;
9057        let mut r#type = None;
9058        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9059            r#type = Some(header.r#type);
9060            let res = match header.r#type {
9061                1u16 => OpQueueGetDumpReply::Id({
9062                    let res = parse_u32(next);
9063                    let Some(val) = res else { break };
9064                    val
9065                }),
9066                2u16 => OpQueueGetDumpReply::Ifindex({
9067                    let res = parse_u32(next);
9068                    let Some(val) = res else { break };
9069                    val
9070                }),
9071                3u16 => OpQueueGetDumpReply::Type({
9072                    let res = parse_u32(next);
9073                    let Some(val) = res else { break };
9074                    val
9075                }),
9076                4u16 => OpQueueGetDumpReply::NapiId({
9077                    let res = parse_u32(next);
9078                    let Some(val) = res else { break };
9079                    val
9080                }),
9081                5u16 => OpQueueGetDumpReply::Dmabuf({
9082                    let res = parse_u32(next);
9083                    let Some(val) = res else { break };
9084                    val
9085                }),
9086                6u16 => OpQueueGetDumpReply::IoUring({
9087                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9088                    let Some(val) = res else { break };
9089                    val
9090                }),
9091                7u16 => OpQueueGetDumpReply::Xsk({
9092                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9093                    let Some(val) = res else { break };
9094                    val
9095                }),
9096                n => {
9097                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
9098                        break;
9099                    } else {
9100                        continue;
9101                    }
9102                }
9103            };
9104            return Some(Ok(res));
9105        }
9106        Some(Err(ErrorContext::new(
9107            "OpQueueGetDumpReply",
9108            r#type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9109            self.orig_loc,
9110            self.buf.as_ptr().wrapping_add(pos) as usize,
9111        )))
9112    }
9113}
9114impl<'a> std::fmt::Debug for IterableOpQueueGetDumpReply<'_> {
9115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9116        let mut fmt = f.debug_struct("OpQueueGetDumpReply");
9117        for attr in self.clone() {
9118            let attr = match attr {
9119                Ok(a) => a,
9120                Err(err) => {
9121                    fmt.finish()?;
9122                    f.write_str("Err(")?;
9123                    err.fmt(f)?;
9124                    return f.write_str(")");
9125                }
9126            };
9127            match attr {
9128                OpQueueGetDumpReply::Id(val) => fmt.field("Id", &val),
9129                OpQueueGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
9130                OpQueueGetDumpReply::Type(val) => {
9131                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9132                }
9133                OpQueueGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
9134                OpQueueGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9135                OpQueueGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
9136                OpQueueGetDumpReply::Xsk(val) => fmt.field("Xsk", &val),
9137            };
9138        }
9139        fmt.finish()
9140    }
9141}
9142impl IterableOpQueueGetDumpReply<'_> {
9143    pub fn lookup_attr(
9144        &self,
9145        offset: usize,
9146        missing_type: Option<u16>,
9147    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9148        let mut stack = Vec::new();
9149        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9150        if cur == offset + PushBuiltinNfgenmsg::len() {
9151            stack.push(("OpQueueGetDumpReply", offset));
9152            return (
9153                stack,
9154                missing_type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9155            );
9156        }
9157        if cur > offset || cur + self.buf.len() < offset {
9158            return (stack, None);
9159        }
9160        let mut attrs = self.clone();
9161        let mut last_off = cur + attrs.pos;
9162        let mut missing = None;
9163        while let Some(attr) = attrs.next() {
9164            let Ok(attr) = attr else { break };
9165            match attr {
9166                OpQueueGetDumpReply::Id(val) => {
9167                    if last_off == offset {
9168                        stack.push(("Id", last_off));
9169                        break;
9170                    }
9171                }
9172                OpQueueGetDumpReply::Ifindex(val) => {
9173                    if last_off == offset {
9174                        stack.push(("Ifindex", last_off));
9175                        break;
9176                    }
9177                }
9178                OpQueueGetDumpReply::Type(val) => {
9179                    if last_off == offset {
9180                        stack.push(("Type", last_off));
9181                        break;
9182                    }
9183                }
9184                OpQueueGetDumpReply::NapiId(val) => {
9185                    if last_off == offset {
9186                        stack.push(("NapiId", last_off));
9187                        break;
9188                    }
9189                }
9190                OpQueueGetDumpReply::Dmabuf(val) => {
9191                    if last_off == offset {
9192                        stack.push(("Dmabuf", last_off));
9193                        break;
9194                    }
9195                }
9196                OpQueueGetDumpReply::IoUring(val) => {
9197                    (stack, missing) = val.lookup_attr(offset, missing_type);
9198                    if !stack.is_empty() {
9199                        break;
9200                    }
9201                }
9202                OpQueueGetDumpReply::Xsk(val) => {
9203                    (stack, missing) = val.lookup_attr(offset, missing_type);
9204                    if !stack.is_empty() {
9205                        break;
9206                    }
9207                }
9208                _ => {}
9209            };
9210            last_off = cur + attrs.pos;
9211        }
9212        if !stack.is_empty() {
9213            stack.push(("OpQueueGetDumpReply", cur));
9214        }
9215        (stack, missing)
9216    }
9217}
9218#[derive(Debug)]
9219pub struct RequestOpQueueGetDumpRequest<'r> {
9220    request: Request<'r>,
9221}
9222impl<'r> RequestOpQueueGetDumpRequest<'r> {
9223    pub fn new(mut request: Request<'r>) -> Self {
9224        PushOpQueueGetDumpRequest::write_header(&mut request.buf_mut());
9225        Self {
9226            request: request.set_dump(),
9227        }
9228    }
9229    pub fn encode(&mut self) -> PushOpQueueGetDumpRequest<&mut Vec<u8>> {
9230        PushOpQueueGetDumpRequest::new_without_header(self.request.buf_mut())
9231    }
9232    pub fn into_encoder(self) -> PushOpQueueGetDumpRequest<RequestBuf<'r>> {
9233        PushOpQueueGetDumpRequest::new_without_header(self.request.buf)
9234    }
9235}
9236impl NetlinkRequest for RequestOpQueueGetDumpRequest<'_> {
9237    type ReplyType<'buf> = IterableOpQueueGetDumpReply<'buf>;
9238    fn protocol(&self) -> Protocol {
9239        Protocol::Generic("netdev".as_bytes())
9240    }
9241    fn flags(&self) -> u16 {
9242        self.request.flags
9243    }
9244    fn payload(&self) -> &[u8] {
9245        self.request.buf()
9246    }
9247    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9248        OpQueueGetDumpReply::new(buf)
9249    }
9250    fn lookup(
9251        buf: &[u8],
9252        offset: usize,
9253        missing_type: Option<u16>,
9254    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9255        OpQueueGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
9256    }
9257}
9258#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9259pub struct PushOpQueueGetDoRequest<Prev: Rec> {
9260    pub(crate) prev: Option<Prev>,
9261    pub(crate) header_offset: Option<usize>,
9262}
9263impl<Prev: Rec> Rec for PushOpQueueGetDoRequest<Prev> {
9264    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9265        self.prev.as_mut().unwrap().as_rec_mut()
9266    }
9267}
9268impl<Prev: Rec> PushOpQueueGetDoRequest<Prev> {
9269    pub fn new(mut prev: Prev) -> Self {
9270        Self::write_header(&mut prev);
9271        Self::new_without_header(prev)
9272    }
9273    fn new_without_header(prev: Prev) -> Self {
9274        Self {
9275            prev: Some(prev),
9276            header_offset: None,
9277        }
9278    }
9279    fn write_header(prev: &mut Prev) {
9280        let mut header = PushBuiltinNfgenmsg::new();
9281        header.set_cmd(10u8);
9282        header.set_version(1u8);
9283        prev.as_rec_mut().extend(header.as_slice());
9284    }
9285    pub fn end_nested(mut self) -> Prev {
9286        let mut prev = self.prev.take().unwrap();
9287        if let Some(header_offset) = &self.header_offset {
9288            finalize_nested_header(prev.as_rec_mut(), *header_offset);
9289        }
9290        prev
9291    }
9292    #[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."]
9293    pub fn push_id(mut self, value: u32) -> Self {
9294        push_header(self.as_rec_mut(), 1u16, 4 as u16);
9295        self.as_rec_mut().extend(value.to_ne_bytes());
9296        self
9297    }
9298    #[doc = "ifindex of the netdevice to which the queue belongs."]
9299    pub fn push_ifindex(mut self, value: u32) -> Self {
9300        push_header(self.as_rec_mut(), 2u16, 4 as u16);
9301        self.as_rec_mut().extend(value.to_ne_bytes());
9302        self
9303    }
9304    #[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)"]
9305    pub fn push_type(mut self, value: u32) -> Self {
9306        push_header(self.as_rec_mut(), 3u16, 4 as u16);
9307        self.as_rec_mut().extend(value.to_ne_bytes());
9308        self
9309    }
9310}
9311impl<Prev: Rec> Drop for PushOpQueueGetDoRequest<Prev> {
9312    fn drop(&mut self) {
9313        if let Some(prev) = &mut self.prev {
9314            if let Some(header_offset) = &self.header_offset {
9315                finalize_nested_header(prev.as_rec_mut(), *header_offset);
9316            }
9317        }
9318    }
9319}
9320#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9321#[derive(Clone)]
9322pub enum OpQueueGetDoRequest {
9323    #[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."]
9324    Id(u32),
9325    #[doc = "ifindex of the netdevice to which the queue belongs."]
9326    Ifindex(u32),
9327    #[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)"]
9328    Type(u32),
9329}
9330impl<'a> IterableOpQueueGetDoRequest<'a> {
9331    #[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."]
9332    pub fn get_id(&self) -> Result<u32, ErrorContext> {
9333        let mut iter = self.clone();
9334        iter.pos = 0;
9335        for attr in iter {
9336            if let OpQueueGetDoRequest::Id(val) = attr? {
9337                return Ok(val);
9338            }
9339        }
9340        Err(ErrorContext::new_missing(
9341            "OpQueueGetDoRequest",
9342            "Id",
9343            self.orig_loc,
9344            self.buf.as_ptr() as usize,
9345        ))
9346    }
9347    #[doc = "ifindex of the netdevice to which the queue belongs."]
9348    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9349        let mut iter = self.clone();
9350        iter.pos = 0;
9351        for attr in iter {
9352            if let OpQueueGetDoRequest::Ifindex(val) = attr? {
9353                return Ok(val);
9354            }
9355        }
9356        Err(ErrorContext::new_missing(
9357            "OpQueueGetDoRequest",
9358            "Ifindex",
9359            self.orig_loc,
9360            self.buf.as_ptr() as usize,
9361        ))
9362    }
9363    #[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)"]
9364    pub fn get_type(&self) -> Result<u32, ErrorContext> {
9365        let mut iter = self.clone();
9366        iter.pos = 0;
9367        for attr in iter {
9368            if let OpQueueGetDoRequest::Type(val) = attr? {
9369                return Ok(val);
9370            }
9371        }
9372        Err(ErrorContext::new_missing(
9373            "OpQueueGetDoRequest",
9374            "Type",
9375            self.orig_loc,
9376            self.buf.as_ptr() as usize,
9377        ))
9378    }
9379}
9380impl OpQueueGetDoRequest {
9381    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoRequest<'a> {
9382        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9383        IterableOpQueueGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
9384    }
9385    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9386        Queue::attr_from_type(r#type)
9387    }
9388}
9389#[derive(Clone, Copy, Default)]
9390pub struct IterableOpQueueGetDoRequest<'a> {
9391    buf: &'a [u8],
9392    pos: usize,
9393    orig_loc: usize,
9394}
9395impl<'a> IterableOpQueueGetDoRequest<'a> {
9396    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9397        Self {
9398            buf,
9399            pos: 0,
9400            orig_loc,
9401        }
9402    }
9403    pub fn get_buf(&self) -> &'a [u8] {
9404        self.buf
9405    }
9406}
9407impl<'a> Iterator for IterableOpQueueGetDoRequest<'a> {
9408    type Item = Result<OpQueueGetDoRequest, ErrorContext>;
9409    fn next(&mut self) -> Option<Self::Item> {
9410        if self.buf.len() == self.pos {
9411            return None;
9412        }
9413        let pos = self.pos;
9414        let mut r#type = None;
9415        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9416            r#type = Some(header.r#type);
9417            let res = match header.r#type {
9418                1u16 => OpQueueGetDoRequest::Id({
9419                    let res = parse_u32(next);
9420                    let Some(val) = res else { break };
9421                    val
9422                }),
9423                2u16 => OpQueueGetDoRequest::Ifindex({
9424                    let res = parse_u32(next);
9425                    let Some(val) = res else { break };
9426                    val
9427                }),
9428                3u16 => OpQueueGetDoRequest::Type({
9429                    let res = parse_u32(next);
9430                    let Some(val) = res else { break };
9431                    val
9432                }),
9433                n => {
9434                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
9435                        break;
9436                    } else {
9437                        continue;
9438                    }
9439                }
9440            };
9441            return Some(Ok(res));
9442        }
9443        Some(Err(ErrorContext::new(
9444            "OpQueueGetDoRequest",
9445            r#type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9446            self.orig_loc,
9447            self.buf.as_ptr().wrapping_add(pos) as usize,
9448        )))
9449    }
9450}
9451impl std::fmt::Debug for IterableOpQueueGetDoRequest<'_> {
9452    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9453        let mut fmt = f.debug_struct("OpQueueGetDoRequest");
9454        for attr in self.clone() {
9455            let attr = match attr {
9456                Ok(a) => a,
9457                Err(err) => {
9458                    fmt.finish()?;
9459                    f.write_str("Err(")?;
9460                    err.fmt(f)?;
9461                    return f.write_str(")");
9462                }
9463            };
9464            match attr {
9465                OpQueueGetDoRequest::Id(val) => fmt.field("Id", &val),
9466                OpQueueGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
9467                OpQueueGetDoRequest::Type(val) => {
9468                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9469                }
9470            };
9471        }
9472        fmt.finish()
9473    }
9474}
9475impl IterableOpQueueGetDoRequest<'_> {
9476    pub fn lookup_attr(
9477        &self,
9478        offset: usize,
9479        missing_type: Option<u16>,
9480    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9481        let mut stack = Vec::new();
9482        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9483        if cur == offset + PushBuiltinNfgenmsg::len() {
9484            stack.push(("OpQueueGetDoRequest", offset));
9485            return (
9486                stack,
9487                missing_type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9488            );
9489        }
9490        if cur > offset || cur + self.buf.len() < offset {
9491            return (stack, None);
9492        }
9493        let mut attrs = self.clone();
9494        let mut last_off = cur + attrs.pos;
9495        while let Some(attr) = attrs.next() {
9496            let Ok(attr) = attr else { break };
9497            match attr {
9498                OpQueueGetDoRequest::Id(val) => {
9499                    if last_off == offset {
9500                        stack.push(("Id", last_off));
9501                        break;
9502                    }
9503                }
9504                OpQueueGetDoRequest::Ifindex(val) => {
9505                    if last_off == offset {
9506                        stack.push(("Ifindex", last_off));
9507                        break;
9508                    }
9509                }
9510                OpQueueGetDoRequest::Type(val) => {
9511                    if last_off == offset {
9512                        stack.push(("Type", last_off));
9513                        break;
9514                    }
9515                }
9516                _ => {}
9517            };
9518            last_off = cur + attrs.pos;
9519        }
9520        if !stack.is_empty() {
9521            stack.push(("OpQueueGetDoRequest", cur));
9522        }
9523        (stack, None)
9524    }
9525}
9526#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9527pub struct PushOpQueueGetDoReply<Prev: Rec> {
9528    pub(crate) prev: Option<Prev>,
9529    pub(crate) header_offset: Option<usize>,
9530}
9531impl<Prev: Rec> Rec for PushOpQueueGetDoReply<Prev> {
9532    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9533        self.prev.as_mut().unwrap().as_rec_mut()
9534    }
9535}
9536impl<Prev: Rec> PushOpQueueGetDoReply<Prev> {
9537    pub fn new(mut prev: Prev) -> Self {
9538        Self::write_header(&mut prev);
9539        Self::new_without_header(prev)
9540    }
9541    fn new_without_header(prev: Prev) -> Self {
9542        Self {
9543            prev: Some(prev),
9544            header_offset: None,
9545        }
9546    }
9547    fn write_header(prev: &mut Prev) {
9548        let mut header = PushBuiltinNfgenmsg::new();
9549        header.set_cmd(10u8);
9550        header.set_version(1u8);
9551        prev.as_rec_mut().extend(header.as_slice());
9552    }
9553    pub fn end_nested(mut self) -> Prev {
9554        let mut prev = self.prev.take().unwrap();
9555        if let Some(header_offset) = &self.header_offset {
9556            finalize_nested_header(prev.as_rec_mut(), *header_offset);
9557        }
9558        prev
9559    }
9560    #[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."]
9561    pub fn push_id(mut self, value: u32) -> Self {
9562        push_header(self.as_rec_mut(), 1u16, 4 as u16);
9563        self.as_rec_mut().extend(value.to_ne_bytes());
9564        self
9565    }
9566    #[doc = "ifindex of the netdevice to which the queue belongs."]
9567    pub fn push_ifindex(mut self, value: u32) -> Self {
9568        push_header(self.as_rec_mut(), 2u16, 4 as u16);
9569        self.as_rec_mut().extend(value.to_ne_bytes());
9570        self
9571    }
9572    #[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)"]
9573    pub fn push_type(mut self, value: u32) -> Self {
9574        push_header(self.as_rec_mut(), 3u16, 4 as u16);
9575        self.as_rec_mut().extend(value.to_ne_bytes());
9576        self
9577    }
9578    #[doc = "ID of the NAPI instance which services this queue."]
9579    pub fn push_napi_id(mut self, value: u32) -> Self {
9580        push_header(self.as_rec_mut(), 4u16, 4 as u16);
9581        self.as_rec_mut().extend(value.to_ne_bytes());
9582        self
9583    }
9584    #[doc = "ID of the dmabuf attached to this queue, if any."]
9585    pub fn push_dmabuf(mut self, value: u32) -> Self {
9586        push_header(self.as_rec_mut(), 5u16, 4 as u16);
9587        self.as_rec_mut().extend(value.to_ne_bytes());
9588        self
9589    }
9590    #[doc = "io_uring memory provider information."]
9591    pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
9592        let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
9593        PushIoUringProviderInfo {
9594            prev: Some(self),
9595            header_offset: Some(header_offset),
9596        }
9597    }
9598    #[doc = "XSK information for this queue, if any."]
9599    pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
9600        let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
9601        PushXskInfo {
9602            prev: Some(self),
9603            header_offset: Some(header_offset),
9604        }
9605    }
9606}
9607impl<Prev: Rec> Drop for PushOpQueueGetDoReply<Prev> {
9608    fn drop(&mut self) {
9609        if let Some(prev) = &mut self.prev {
9610            if let Some(header_offset) = &self.header_offset {
9611                finalize_nested_header(prev.as_rec_mut(), *header_offset);
9612            }
9613        }
9614    }
9615}
9616#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9617#[derive(Clone)]
9618pub enum OpQueueGetDoReply<'a> {
9619    #[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."]
9620    Id(u32),
9621    #[doc = "ifindex of the netdevice to which the queue belongs."]
9622    Ifindex(u32),
9623    #[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)"]
9624    Type(u32),
9625    #[doc = "ID of the NAPI instance which services this queue."]
9626    NapiId(u32),
9627    #[doc = "ID of the dmabuf attached to this queue, if any."]
9628    Dmabuf(u32),
9629    #[doc = "io_uring memory provider information."]
9630    IoUring(IterableIoUringProviderInfo<'a>),
9631    #[doc = "XSK information for this queue, if any."]
9632    Xsk(IterableXskInfo<'a>),
9633}
9634impl<'a> IterableOpQueueGetDoReply<'a> {
9635    #[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."]
9636    pub fn get_id(&self) -> Result<u32, ErrorContext> {
9637        let mut iter = self.clone();
9638        iter.pos = 0;
9639        for attr in iter {
9640            if let OpQueueGetDoReply::Id(val) = attr? {
9641                return Ok(val);
9642            }
9643        }
9644        Err(ErrorContext::new_missing(
9645            "OpQueueGetDoReply",
9646            "Id",
9647            self.orig_loc,
9648            self.buf.as_ptr() as usize,
9649        ))
9650    }
9651    #[doc = "ifindex of the netdevice to which the queue belongs."]
9652    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9653        let mut iter = self.clone();
9654        iter.pos = 0;
9655        for attr in iter {
9656            if let OpQueueGetDoReply::Ifindex(val) = attr? {
9657                return Ok(val);
9658            }
9659        }
9660        Err(ErrorContext::new_missing(
9661            "OpQueueGetDoReply",
9662            "Ifindex",
9663            self.orig_loc,
9664            self.buf.as_ptr() as usize,
9665        ))
9666    }
9667    #[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)"]
9668    pub fn get_type(&self) -> Result<u32, ErrorContext> {
9669        let mut iter = self.clone();
9670        iter.pos = 0;
9671        for attr in iter {
9672            if let OpQueueGetDoReply::Type(val) = attr? {
9673                return Ok(val);
9674            }
9675        }
9676        Err(ErrorContext::new_missing(
9677            "OpQueueGetDoReply",
9678            "Type",
9679            self.orig_loc,
9680            self.buf.as_ptr() as usize,
9681        ))
9682    }
9683    #[doc = "ID of the NAPI instance which services this queue."]
9684    pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9685        let mut iter = self.clone();
9686        iter.pos = 0;
9687        for attr in iter {
9688            if let OpQueueGetDoReply::NapiId(val) = attr? {
9689                return Ok(val);
9690            }
9691        }
9692        Err(ErrorContext::new_missing(
9693            "OpQueueGetDoReply",
9694            "NapiId",
9695            self.orig_loc,
9696            self.buf.as_ptr() as usize,
9697        ))
9698    }
9699    #[doc = "ID of the dmabuf attached to this queue, if any."]
9700    pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9701        let mut iter = self.clone();
9702        iter.pos = 0;
9703        for attr in iter {
9704            if let OpQueueGetDoReply::Dmabuf(val) = attr? {
9705                return Ok(val);
9706            }
9707        }
9708        Err(ErrorContext::new_missing(
9709            "OpQueueGetDoReply",
9710            "Dmabuf",
9711            self.orig_loc,
9712            self.buf.as_ptr() as usize,
9713        ))
9714    }
9715    #[doc = "io_uring memory provider information."]
9716    pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9717        let mut iter = self.clone();
9718        iter.pos = 0;
9719        for attr in iter {
9720            if let OpQueueGetDoReply::IoUring(val) = attr? {
9721                return Ok(val);
9722            }
9723        }
9724        Err(ErrorContext::new_missing(
9725            "OpQueueGetDoReply",
9726            "IoUring",
9727            self.orig_loc,
9728            self.buf.as_ptr() as usize,
9729        ))
9730    }
9731    #[doc = "XSK information for this queue, if any."]
9732    pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9733        let mut iter = self.clone();
9734        iter.pos = 0;
9735        for attr in iter {
9736            if let OpQueueGetDoReply::Xsk(val) = attr? {
9737                return Ok(val);
9738            }
9739        }
9740        Err(ErrorContext::new_missing(
9741            "OpQueueGetDoReply",
9742            "Xsk",
9743            self.orig_loc,
9744            self.buf.as_ptr() as usize,
9745        ))
9746    }
9747}
9748impl OpQueueGetDoReply<'_> {
9749    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoReply<'a> {
9750        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9751        IterableOpQueueGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
9752    }
9753    fn attr_from_type(r#type: u16) -> Option<&'static str> {
9754        Queue::attr_from_type(r#type)
9755    }
9756}
9757#[derive(Clone, Copy, Default)]
9758pub struct IterableOpQueueGetDoReply<'a> {
9759    buf: &'a [u8],
9760    pos: usize,
9761    orig_loc: usize,
9762}
9763impl<'a> IterableOpQueueGetDoReply<'a> {
9764    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9765        Self {
9766            buf,
9767            pos: 0,
9768            orig_loc,
9769        }
9770    }
9771    pub fn get_buf(&self) -> &'a [u8] {
9772        self.buf
9773    }
9774}
9775impl<'a> Iterator for IterableOpQueueGetDoReply<'a> {
9776    type Item = Result<OpQueueGetDoReply<'a>, ErrorContext>;
9777    fn next(&mut self) -> Option<Self::Item> {
9778        if self.buf.len() == self.pos {
9779            return None;
9780        }
9781        let pos = self.pos;
9782        let mut r#type = None;
9783        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9784            r#type = Some(header.r#type);
9785            let res = match header.r#type {
9786                1u16 => OpQueueGetDoReply::Id({
9787                    let res = parse_u32(next);
9788                    let Some(val) = res else { break };
9789                    val
9790                }),
9791                2u16 => OpQueueGetDoReply::Ifindex({
9792                    let res = parse_u32(next);
9793                    let Some(val) = res else { break };
9794                    val
9795                }),
9796                3u16 => OpQueueGetDoReply::Type({
9797                    let res = parse_u32(next);
9798                    let Some(val) = res else { break };
9799                    val
9800                }),
9801                4u16 => OpQueueGetDoReply::NapiId({
9802                    let res = parse_u32(next);
9803                    let Some(val) = res else { break };
9804                    val
9805                }),
9806                5u16 => OpQueueGetDoReply::Dmabuf({
9807                    let res = parse_u32(next);
9808                    let Some(val) = res else { break };
9809                    val
9810                }),
9811                6u16 => OpQueueGetDoReply::IoUring({
9812                    let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9813                    let Some(val) = res else { break };
9814                    val
9815                }),
9816                7u16 => OpQueueGetDoReply::Xsk({
9817                    let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9818                    let Some(val) = res else { break };
9819                    val
9820                }),
9821                n => {
9822                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
9823                        break;
9824                    } else {
9825                        continue;
9826                    }
9827                }
9828            };
9829            return Some(Ok(res));
9830        }
9831        Some(Err(ErrorContext::new(
9832            "OpQueueGetDoReply",
9833            r#type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9834            self.orig_loc,
9835            self.buf.as_ptr().wrapping_add(pos) as usize,
9836        )))
9837    }
9838}
9839impl<'a> std::fmt::Debug for IterableOpQueueGetDoReply<'_> {
9840    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9841        let mut fmt = f.debug_struct("OpQueueGetDoReply");
9842        for attr in self.clone() {
9843            let attr = match attr {
9844                Ok(a) => a,
9845                Err(err) => {
9846                    fmt.finish()?;
9847                    f.write_str("Err(")?;
9848                    err.fmt(f)?;
9849                    return f.write_str(")");
9850                }
9851            };
9852            match attr {
9853                OpQueueGetDoReply::Id(val) => fmt.field("Id", &val),
9854                OpQueueGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
9855                OpQueueGetDoReply::Type(val) => {
9856                    fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9857                }
9858                OpQueueGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
9859                OpQueueGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9860                OpQueueGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
9861                OpQueueGetDoReply::Xsk(val) => fmt.field("Xsk", &val),
9862            };
9863        }
9864        fmt.finish()
9865    }
9866}
9867impl IterableOpQueueGetDoReply<'_> {
9868    pub fn lookup_attr(
9869        &self,
9870        offset: usize,
9871        missing_type: Option<u16>,
9872    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9873        let mut stack = Vec::new();
9874        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9875        if cur == offset + PushBuiltinNfgenmsg::len() {
9876            stack.push(("OpQueueGetDoReply", offset));
9877            return (
9878                stack,
9879                missing_type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9880            );
9881        }
9882        if cur > offset || cur + self.buf.len() < offset {
9883            return (stack, None);
9884        }
9885        let mut attrs = self.clone();
9886        let mut last_off = cur + attrs.pos;
9887        let mut missing = None;
9888        while let Some(attr) = attrs.next() {
9889            let Ok(attr) = attr else { break };
9890            match attr {
9891                OpQueueGetDoReply::Id(val) => {
9892                    if last_off == offset {
9893                        stack.push(("Id", last_off));
9894                        break;
9895                    }
9896                }
9897                OpQueueGetDoReply::Ifindex(val) => {
9898                    if last_off == offset {
9899                        stack.push(("Ifindex", last_off));
9900                        break;
9901                    }
9902                }
9903                OpQueueGetDoReply::Type(val) => {
9904                    if last_off == offset {
9905                        stack.push(("Type", last_off));
9906                        break;
9907                    }
9908                }
9909                OpQueueGetDoReply::NapiId(val) => {
9910                    if last_off == offset {
9911                        stack.push(("NapiId", last_off));
9912                        break;
9913                    }
9914                }
9915                OpQueueGetDoReply::Dmabuf(val) => {
9916                    if last_off == offset {
9917                        stack.push(("Dmabuf", last_off));
9918                        break;
9919                    }
9920                }
9921                OpQueueGetDoReply::IoUring(val) => {
9922                    (stack, missing) = val.lookup_attr(offset, missing_type);
9923                    if !stack.is_empty() {
9924                        break;
9925                    }
9926                }
9927                OpQueueGetDoReply::Xsk(val) => {
9928                    (stack, missing) = val.lookup_attr(offset, missing_type);
9929                    if !stack.is_empty() {
9930                        break;
9931                    }
9932                }
9933                _ => {}
9934            };
9935            last_off = cur + attrs.pos;
9936        }
9937        if !stack.is_empty() {
9938            stack.push(("OpQueueGetDoReply", cur));
9939        }
9940        (stack, missing)
9941    }
9942}
9943#[derive(Debug)]
9944pub struct RequestOpQueueGetDoRequest<'r> {
9945    request: Request<'r>,
9946}
9947impl<'r> RequestOpQueueGetDoRequest<'r> {
9948    pub fn new(mut request: Request<'r>) -> Self {
9949        PushOpQueueGetDoRequest::write_header(&mut request.buf_mut());
9950        Self { request: request }
9951    }
9952    pub fn encode(&mut self) -> PushOpQueueGetDoRequest<&mut Vec<u8>> {
9953        PushOpQueueGetDoRequest::new_without_header(self.request.buf_mut())
9954    }
9955    pub fn into_encoder(self) -> PushOpQueueGetDoRequest<RequestBuf<'r>> {
9956        PushOpQueueGetDoRequest::new_without_header(self.request.buf)
9957    }
9958}
9959impl NetlinkRequest for RequestOpQueueGetDoRequest<'_> {
9960    type ReplyType<'buf> = IterableOpQueueGetDoReply<'buf>;
9961    fn protocol(&self) -> Protocol {
9962        Protocol::Generic("netdev".as_bytes())
9963    }
9964    fn flags(&self) -> u16 {
9965        self.request.flags
9966    }
9967    fn payload(&self) -> &[u8] {
9968        self.request.buf()
9969    }
9970    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9971        OpQueueGetDoReply::new(buf)
9972    }
9973    fn lookup(
9974        buf: &[u8],
9975        offset: usize,
9976        missing_type: Option<u16>,
9977    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9978        OpQueueGetDoRequest::new(buf).lookup_attr(offset, missing_type)
9979    }
9980}
9981#[doc = "Get information about NAPI instances configured on the system."]
9982pub struct PushOpNapiGetDumpRequest<Prev: Rec> {
9983    pub(crate) prev: Option<Prev>,
9984    pub(crate) header_offset: Option<usize>,
9985}
9986impl<Prev: Rec> Rec for PushOpNapiGetDumpRequest<Prev> {
9987    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9988        self.prev.as_mut().unwrap().as_rec_mut()
9989    }
9990}
9991impl<Prev: Rec> PushOpNapiGetDumpRequest<Prev> {
9992    pub fn new(mut prev: Prev) -> Self {
9993        Self::write_header(&mut prev);
9994        Self::new_without_header(prev)
9995    }
9996    fn new_without_header(prev: Prev) -> Self {
9997        Self {
9998            prev: Some(prev),
9999            header_offset: None,
10000        }
10001    }
10002    fn write_header(prev: &mut Prev) {
10003        let mut header = PushBuiltinNfgenmsg::new();
10004        header.set_cmd(11u8);
10005        header.set_version(1u8);
10006        prev.as_rec_mut().extend(header.as_slice());
10007    }
10008    pub fn end_nested(mut self) -> Prev {
10009        let mut prev = self.prev.take().unwrap();
10010        if let Some(header_offset) = &self.header_offset {
10011            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10012        }
10013        prev
10014    }
10015    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10016    pub fn push_ifindex(mut self, value: u32) -> Self {
10017        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10018        self.as_rec_mut().extend(value.to_ne_bytes());
10019        self
10020    }
10021}
10022impl<Prev: Rec> Drop for PushOpNapiGetDumpRequest<Prev> {
10023    fn drop(&mut self) {
10024        if let Some(prev) = &mut self.prev {
10025            if let Some(header_offset) = &self.header_offset {
10026                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10027            }
10028        }
10029    }
10030}
10031#[doc = "Get information about NAPI instances configured on the system."]
10032#[derive(Clone)]
10033pub enum OpNapiGetDumpRequest {
10034    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10035    Ifindex(u32),
10036}
10037impl<'a> IterableOpNapiGetDumpRequest<'a> {
10038    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10039    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10040        let mut iter = self.clone();
10041        iter.pos = 0;
10042        for attr in iter {
10043            if let OpNapiGetDumpRequest::Ifindex(val) = attr? {
10044                return Ok(val);
10045            }
10046        }
10047        Err(ErrorContext::new_missing(
10048            "OpNapiGetDumpRequest",
10049            "Ifindex",
10050            self.orig_loc,
10051            self.buf.as_ptr() as usize,
10052        ))
10053    }
10054}
10055impl OpNapiGetDumpRequest {
10056    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpRequest<'a> {
10057        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10058        IterableOpNapiGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
10059    }
10060    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10061        Napi::attr_from_type(r#type)
10062    }
10063}
10064#[derive(Clone, Copy, Default)]
10065pub struct IterableOpNapiGetDumpRequest<'a> {
10066    buf: &'a [u8],
10067    pos: usize,
10068    orig_loc: usize,
10069}
10070impl<'a> IterableOpNapiGetDumpRequest<'a> {
10071    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10072        Self {
10073            buf,
10074            pos: 0,
10075            orig_loc,
10076        }
10077    }
10078    pub fn get_buf(&self) -> &'a [u8] {
10079        self.buf
10080    }
10081}
10082impl<'a> Iterator for IterableOpNapiGetDumpRequest<'a> {
10083    type Item = Result<OpNapiGetDumpRequest, ErrorContext>;
10084    fn next(&mut self) -> Option<Self::Item> {
10085        if self.buf.len() == self.pos {
10086            return None;
10087        }
10088        let pos = self.pos;
10089        let mut r#type = None;
10090        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10091            r#type = Some(header.r#type);
10092            let res = match header.r#type {
10093                1u16 => OpNapiGetDumpRequest::Ifindex({
10094                    let res = parse_u32(next);
10095                    let Some(val) = res else { break };
10096                    val
10097                }),
10098                n => {
10099                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
10100                        break;
10101                    } else {
10102                        continue;
10103                    }
10104                }
10105            };
10106            return Some(Ok(res));
10107        }
10108        Some(Err(ErrorContext::new(
10109            "OpNapiGetDumpRequest",
10110            r#type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10111            self.orig_loc,
10112            self.buf.as_ptr().wrapping_add(pos) as usize,
10113        )))
10114    }
10115}
10116impl std::fmt::Debug for IterableOpNapiGetDumpRequest<'_> {
10117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10118        let mut fmt = f.debug_struct("OpNapiGetDumpRequest");
10119        for attr in self.clone() {
10120            let attr = match attr {
10121                Ok(a) => a,
10122                Err(err) => {
10123                    fmt.finish()?;
10124                    f.write_str("Err(")?;
10125                    err.fmt(f)?;
10126                    return f.write_str(")");
10127                }
10128            };
10129            match attr {
10130                OpNapiGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
10131            };
10132        }
10133        fmt.finish()
10134    }
10135}
10136impl IterableOpNapiGetDumpRequest<'_> {
10137    pub fn lookup_attr(
10138        &self,
10139        offset: usize,
10140        missing_type: Option<u16>,
10141    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10142        let mut stack = Vec::new();
10143        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10144        if cur == offset + PushBuiltinNfgenmsg::len() {
10145            stack.push(("OpNapiGetDumpRequest", offset));
10146            return (
10147                stack,
10148                missing_type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10149            );
10150        }
10151        if cur > offset || cur + self.buf.len() < offset {
10152            return (stack, None);
10153        }
10154        let mut attrs = self.clone();
10155        let mut last_off = cur + attrs.pos;
10156        while let Some(attr) = attrs.next() {
10157            let Ok(attr) = attr else { break };
10158            match attr {
10159                OpNapiGetDumpRequest::Ifindex(val) => {
10160                    if last_off == offset {
10161                        stack.push(("Ifindex", last_off));
10162                        break;
10163                    }
10164                }
10165                _ => {}
10166            };
10167            last_off = cur + attrs.pos;
10168        }
10169        if !stack.is_empty() {
10170            stack.push(("OpNapiGetDumpRequest", cur));
10171        }
10172        (stack, None)
10173    }
10174}
10175#[doc = "Get information about NAPI instances configured on the system."]
10176pub struct PushOpNapiGetDumpReply<Prev: Rec> {
10177    pub(crate) prev: Option<Prev>,
10178    pub(crate) header_offset: Option<usize>,
10179}
10180impl<Prev: Rec> Rec for PushOpNapiGetDumpReply<Prev> {
10181    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10182        self.prev.as_mut().unwrap().as_rec_mut()
10183    }
10184}
10185impl<Prev: Rec> PushOpNapiGetDumpReply<Prev> {
10186    pub fn new(mut prev: Prev) -> Self {
10187        Self::write_header(&mut prev);
10188        Self::new_without_header(prev)
10189    }
10190    fn new_without_header(prev: Prev) -> Self {
10191        Self {
10192            prev: Some(prev),
10193            header_offset: None,
10194        }
10195    }
10196    fn write_header(prev: &mut Prev) {
10197        let mut header = PushBuiltinNfgenmsg::new();
10198        header.set_cmd(11u8);
10199        header.set_version(1u8);
10200        prev.as_rec_mut().extend(header.as_slice());
10201    }
10202    pub fn end_nested(mut self) -> Prev {
10203        let mut prev = self.prev.take().unwrap();
10204        if let Some(header_offset) = &self.header_offset {
10205            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10206        }
10207        prev
10208    }
10209    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10210    pub fn push_ifindex(mut self, value: u32) -> Self {
10211        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10212        self.as_rec_mut().extend(value.to_ne_bytes());
10213        self
10214    }
10215    #[doc = "ID of the NAPI instance."]
10216    pub fn push_id(mut self, value: u32) -> Self {
10217        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10218        self.as_rec_mut().extend(value.to_ne_bytes());
10219        self
10220    }
10221    #[doc = "The associated interrupt vector number for the napi"]
10222    pub fn push_irq(mut self, value: u32) -> Self {
10223        push_header(self.as_rec_mut(), 3u16, 4 as u16);
10224        self.as_rec_mut().extend(value.to_ne_bytes());
10225        self
10226    }
10227    #[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."]
10228    pub fn push_pid(mut self, value: u32) -> Self {
10229        push_header(self.as_rec_mut(), 4u16, 4 as u16);
10230        self.as_rec_mut().extend(value.to_ne_bytes());
10231        self
10232    }
10233    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10234    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10235        push_header(self.as_rec_mut(), 5u16, 4 as u16);
10236        self.as_rec_mut().extend(value.to_ne_bytes());
10237        self
10238    }
10239    #[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."]
10240    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10241        push_header(self.as_rec_mut(), 6u16, 4 as u16);
10242        self.as_rec_mut().extend(value.to_ne_bytes());
10243        self
10244    }
10245    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10246    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10247        push_header(self.as_rec_mut(), 7u16, 4 as u16);
10248        self.as_rec_mut().extend(value.to_ne_bytes());
10249        self
10250    }
10251    #[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)"]
10252    pub fn push_threaded(mut self, value: u32) -> Self {
10253        push_header(self.as_rec_mut(), 8u16, 4 as u16);
10254        self.as_rec_mut().extend(value.to_ne_bytes());
10255        self
10256    }
10257}
10258impl<Prev: Rec> Drop for PushOpNapiGetDumpReply<Prev> {
10259    fn drop(&mut self) {
10260        if let Some(prev) = &mut self.prev {
10261            if let Some(header_offset) = &self.header_offset {
10262                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10263            }
10264        }
10265    }
10266}
10267#[doc = "Get information about NAPI instances configured on the system."]
10268#[derive(Clone)]
10269pub enum OpNapiGetDumpReply {
10270    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10271    Ifindex(u32),
10272    #[doc = "ID of the NAPI instance."]
10273    Id(u32),
10274    #[doc = "The associated interrupt vector number for the napi"]
10275    Irq(u32),
10276    #[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."]
10277    Pid(u32),
10278    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10279    DeferHardIrqs(u32),
10280    #[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."]
10281    GroFlushTimeout(u32),
10282    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10283    IrqSuspendTimeout(u32),
10284    #[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)"]
10285    Threaded(u32),
10286}
10287impl<'a> IterableOpNapiGetDumpReply<'a> {
10288    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10289    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10290        let mut iter = self.clone();
10291        iter.pos = 0;
10292        for attr in iter {
10293            if let OpNapiGetDumpReply::Ifindex(val) = attr? {
10294                return Ok(val);
10295            }
10296        }
10297        Err(ErrorContext::new_missing(
10298            "OpNapiGetDumpReply",
10299            "Ifindex",
10300            self.orig_loc,
10301            self.buf.as_ptr() as usize,
10302        ))
10303    }
10304    #[doc = "ID of the NAPI instance."]
10305    pub fn get_id(&self) -> Result<u32, ErrorContext> {
10306        let mut iter = self.clone();
10307        iter.pos = 0;
10308        for attr in iter {
10309            if let OpNapiGetDumpReply::Id(val) = attr? {
10310                return Ok(val);
10311            }
10312        }
10313        Err(ErrorContext::new_missing(
10314            "OpNapiGetDumpReply",
10315            "Id",
10316            self.orig_loc,
10317            self.buf.as_ptr() as usize,
10318        ))
10319    }
10320    #[doc = "The associated interrupt vector number for the napi"]
10321    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
10322        let mut iter = self.clone();
10323        iter.pos = 0;
10324        for attr in iter {
10325            if let OpNapiGetDumpReply::Irq(val) = attr? {
10326                return Ok(val);
10327            }
10328        }
10329        Err(ErrorContext::new_missing(
10330            "OpNapiGetDumpReply",
10331            "Irq",
10332            self.orig_loc,
10333            self.buf.as_ptr() as usize,
10334        ))
10335    }
10336    #[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."]
10337    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
10338        let mut iter = self.clone();
10339        iter.pos = 0;
10340        for attr in iter {
10341            if let OpNapiGetDumpReply::Pid(val) = attr? {
10342                return Ok(val);
10343            }
10344        }
10345        Err(ErrorContext::new_missing(
10346            "OpNapiGetDumpReply",
10347            "Pid",
10348            self.orig_loc,
10349            self.buf.as_ptr() as usize,
10350        ))
10351    }
10352    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10353    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
10354        let mut iter = self.clone();
10355        iter.pos = 0;
10356        for attr in iter {
10357            if let OpNapiGetDumpReply::DeferHardIrqs(val) = attr? {
10358                return Ok(val);
10359            }
10360        }
10361        Err(ErrorContext::new_missing(
10362            "OpNapiGetDumpReply",
10363            "DeferHardIrqs",
10364            self.orig_loc,
10365            self.buf.as_ptr() as usize,
10366        ))
10367    }
10368    #[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."]
10369    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
10370        let mut iter = self.clone();
10371        iter.pos = 0;
10372        for attr in iter {
10373            if let OpNapiGetDumpReply::GroFlushTimeout(val) = attr? {
10374                return Ok(val);
10375            }
10376        }
10377        Err(ErrorContext::new_missing(
10378            "OpNapiGetDumpReply",
10379            "GroFlushTimeout",
10380            self.orig_loc,
10381            self.buf.as_ptr() as usize,
10382        ))
10383    }
10384    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10385    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
10386        let mut iter = self.clone();
10387        iter.pos = 0;
10388        for attr in iter {
10389            if let OpNapiGetDumpReply::IrqSuspendTimeout(val) = attr? {
10390                return Ok(val);
10391            }
10392        }
10393        Err(ErrorContext::new_missing(
10394            "OpNapiGetDumpReply",
10395            "IrqSuspendTimeout",
10396            self.orig_loc,
10397            self.buf.as_ptr() as usize,
10398        ))
10399    }
10400    #[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)"]
10401    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
10402        let mut iter = self.clone();
10403        iter.pos = 0;
10404        for attr in iter {
10405            if let OpNapiGetDumpReply::Threaded(val) = attr? {
10406                return Ok(val);
10407            }
10408        }
10409        Err(ErrorContext::new_missing(
10410            "OpNapiGetDumpReply",
10411            "Threaded",
10412            self.orig_loc,
10413            self.buf.as_ptr() as usize,
10414        ))
10415    }
10416}
10417impl OpNapiGetDumpReply {
10418    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpReply<'a> {
10419        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10420        IterableOpNapiGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
10421    }
10422    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10423        Napi::attr_from_type(r#type)
10424    }
10425}
10426#[derive(Clone, Copy, Default)]
10427pub struct IterableOpNapiGetDumpReply<'a> {
10428    buf: &'a [u8],
10429    pos: usize,
10430    orig_loc: usize,
10431}
10432impl<'a> IterableOpNapiGetDumpReply<'a> {
10433    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10434        Self {
10435            buf,
10436            pos: 0,
10437            orig_loc,
10438        }
10439    }
10440    pub fn get_buf(&self) -> &'a [u8] {
10441        self.buf
10442    }
10443}
10444impl<'a> Iterator for IterableOpNapiGetDumpReply<'a> {
10445    type Item = Result<OpNapiGetDumpReply, ErrorContext>;
10446    fn next(&mut self) -> Option<Self::Item> {
10447        if self.buf.len() == self.pos {
10448            return None;
10449        }
10450        let pos = self.pos;
10451        let mut r#type = None;
10452        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10453            r#type = Some(header.r#type);
10454            let res = match header.r#type {
10455                1u16 => OpNapiGetDumpReply::Ifindex({
10456                    let res = parse_u32(next);
10457                    let Some(val) = res else { break };
10458                    val
10459                }),
10460                2u16 => OpNapiGetDumpReply::Id({
10461                    let res = parse_u32(next);
10462                    let Some(val) = res else { break };
10463                    val
10464                }),
10465                3u16 => OpNapiGetDumpReply::Irq({
10466                    let res = parse_u32(next);
10467                    let Some(val) = res else { break };
10468                    val
10469                }),
10470                4u16 => OpNapiGetDumpReply::Pid({
10471                    let res = parse_u32(next);
10472                    let Some(val) = res else { break };
10473                    val
10474                }),
10475                5u16 => OpNapiGetDumpReply::DeferHardIrqs({
10476                    let res = parse_u32(next);
10477                    let Some(val) = res else { break };
10478                    val
10479                }),
10480                6u16 => OpNapiGetDumpReply::GroFlushTimeout({
10481                    let res = parse_u32(next);
10482                    let Some(val) = res else { break };
10483                    val
10484                }),
10485                7u16 => OpNapiGetDumpReply::IrqSuspendTimeout({
10486                    let res = parse_u32(next);
10487                    let Some(val) = res else { break };
10488                    val
10489                }),
10490                8u16 => OpNapiGetDumpReply::Threaded({
10491                    let res = parse_u32(next);
10492                    let Some(val) = res else { break };
10493                    val
10494                }),
10495                n => {
10496                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
10497                        break;
10498                    } else {
10499                        continue;
10500                    }
10501                }
10502            };
10503            return Some(Ok(res));
10504        }
10505        Some(Err(ErrorContext::new(
10506            "OpNapiGetDumpReply",
10507            r#type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10508            self.orig_loc,
10509            self.buf.as_ptr().wrapping_add(pos) as usize,
10510        )))
10511    }
10512}
10513impl std::fmt::Debug for IterableOpNapiGetDumpReply<'_> {
10514    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10515        let mut fmt = f.debug_struct("OpNapiGetDumpReply");
10516        for attr in self.clone() {
10517            let attr = match attr {
10518                Ok(a) => a,
10519                Err(err) => {
10520                    fmt.finish()?;
10521                    f.write_str("Err(")?;
10522                    err.fmt(f)?;
10523                    return f.write_str(")");
10524                }
10525            };
10526            match attr {
10527                OpNapiGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
10528                OpNapiGetDumpReply::Id(val) => fmt.field("Id", &val),
10529                OpNapiGetDumpReply::Irq(val) => fmt.field("Irq", &val),
10530                OpNapiGetDumpReply::Pid(val) => fmt.field("Pid", &val),
10531                OpNapiGetDumpReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
10532                OpNapiGetDumpReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
10533                OpNapiGetDumpReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
10534                OpNapiGetDumpReply::Threaded(val) => fmt.field(
10535                    "Threaded",
10536                    &FormatEnum(val.into(), NapiThreaded::from_value),
10537                ),
10538            };
10539        }
10540        fmt.finish()
10541    }
10542}
10543impl IterableOpNapiGetDumpReply<'_> {
10544    pub fn lookup_attr(
10545        &self,
10546        offset: usize,
10547        missing_type: Option<u16>,
10548    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10549        let mut stack = Vec::new();
10550        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10551        if cur == offset + PushBuiltinNfgenmsg::len() {
10552            stack.push(("OpNapiGetDumpReply", offset));
10553            return (
10554                stack,
10555                missing_type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10556            );
10557        }
10558        if cur > offset || cur + self.buf.len() < offset {
10559            return (stack, None);
10560        }
10561        let mut attrs = self.clone();
10562        let mut last_off = cur + attrs.pos;
10563        while let Some(attr) = attrs.next() {
10564            let Ok(attr) = attr else { break };
10565            match attr {
10566                OpNapiGetDumpReply::Ifindex(val) => {
10567                    if last_off == offset {
10568                        stack.push(("Ifindex", last_off));
10569                        break;
10570                    }
10571                }
10572                OpNapiGetDumpReply::Id(val) => {
10573                    if last_off == offset {
10574                        stack.push(("Id", last_off));
10575                        break;
10576                    }
10577                }
10578                OpNapiGetDumpReply::Irq(val) => {
10579                    if last_off == offset {
10580                        stack.push(("Irq", last_off));
10581                        break;
10582                    }
10583                }
10584                OpNapiGetDumpReply::Pid(val) => {
10585                    if last_off == offset {
10586                        stack.push(("Pid", last_off));
10587                        break;
10588                    }
10589                }
10590                OpNapiGetDumpReply::DeferHardIrqs(val) => {
10591                    if last_off == offset {
10592                        stack.push(("DeferHardIrqs", last_off));
10593                        break;
10594                    }
10595                }
10596                OpNapiGetDumpReply::GroFlushTimeout(val) => {
10597                    if last_off == offset {
10598                        stack.push(("GroFlushTimeout", last_off));
10599                        break;
10600                    }
10601                }
10602                OpNapiGetDumpReply::IrqSuspendTimeout(val) => {
10603                    if last_off == offset {
10604                        stack.push(("IrqSuspendTimeout", last_off));
10605                        break;
10606                    }
10607                }
10608                OpNapiGetDumpReply::Threaded(val) => {
10609                    if last_off == offset {
10610                        stack.push(("Threaded", last_off));
10611                        break;
10612                    }
10613                }
10614                _ => {}
10615            };
10616            last_off = cur + attrs.pos;
10617        }
10618        if !stack.is_empty() {
10619            stack.push(("OpNapiGetDumpReply", cur));
10620        }
10621        (stack, None)
10622    }
10623}
10624#[derive(Debug)]
10625pub struct RequestOpNapiGetDumpRequest<'r> {
10626    request: Request<'r>,
10627}
10628impl<'r> RequestOpNapiGetDumpRequest<'r> {
10629    pub fn new(mut request: Request<'r>) -> Self {
10630        PushOpNapiGetDumpRequest::write_header(&mut request.buf_mut());
10631        Self {
10632            request: request.set_dump(),
10633        }
10634    }
10635    pub fn encode(&mut self) -> PushOpNapiGetDumpRequest<&mut Vec<u8>> {
10636        PushOpNapiGetDumpRequest::new_without_header(self.request.buf_mut())
10637    }
10638    pub fn into_encoder(self) -> PushOpNapiGetDumpRequest<RequestBuf<'r>> {
10639        PushOpNapiGetDumpRequest::new_without_header(self.request.buf)
10640    }
10641}
10642impl NetlinkRequest for RequestOpNapiGetDumpRequest<'_> {
10643    type ReplyType<'buf> = IterableOpNapiGetDumpReply<'buf>;
10644    fn protocol(&self) -> Protocol {
10645        Protocol::Generic("netdev".as_bytes())
10646    }
10647    fn flags(&self) -> u16 {
10648        self.request.flags
10649    }
10650    fn payload(&self) -> &[u8] {
10651        self.request.buf()
10652    }
10653    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10654        OpNapiGetDumpReply::new(buf)
10655    }
10656    fn lookup(
10657        buf: &[u8],
10658        offset: usize,
10659        missing_type: Option<u16>,
10660    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10661        OpNapiGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
10662    }
10663}
10664#[doc = "Get information about NAPI instances configured on the system."]
10665pub struct PushOpNapiGetDoRequest<Prev: Rec> {
10666    pub(crate) prev: Option<Prev>,
10667    pub(crate) header_offset: Option<usize>,
10668}
10669impl<Prev: Rec> Rec for PushOpNapiGetDoRequest<Prev> {
10670    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10671        self.prev.as_mut().unwrap().as_rec_mut()
10672    }
10673}
10674impl<Prev: Rec> PushOpNapiGetDoRequest<Prev> {
10675    pub fn new(mut prev: Prev) -> Self {
10676        Self::write_header(&mut prev);
10677        Self::new_without_header(prev)
10678    }
10679    fn new_without_header(prev: Prev) -> Self {
10680        Self {
10681            prev: Some(prev),
10682            header_offset: None,
10683        }
10684    }
10685    fn write_header(prev: &mut Prev) {
10686        let mut header = PushBuiltinNfgenmsg::new();
10687        header.set_cmd(11u8);
10688        header.set_version(1u8);
10689        prev.as_rec_mut().extend(header.as_slice());
10690    }
10691    pub fn end_nested(mut self) -> Prev {
10692        let mut prev = self.prev.take().unwrap();
10693        if let Some(header_offset) = &self.header_offset {
10694            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10695        }
10696        prev
10697    }
10698    #[doc = "ID of the NAPI instance."]
10699    pub fn push_id(mut self, value: u32) -> Self {
10700        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10701        self.as_rec_mut().extend(value.to_ne_bytes());
10702        self
10703    }
10704}
10705impl<Prev: Rec> Drop for PushOpNapiGetDoRequest<Prev> {
10706    fn drop(&mut self) {
10707        if let Some(prev) = &mut self.prev {
10708            if let Some(header_offset) = &self.header_offset {
10709                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10710            }
10711        }
10712    }
10713}
10714#[doc = "Get information about NAPI instances configured on the system."]
10715#[derive(Clone)]
10716pub enum OpNapiGetDoRequest {
10717    #[doc = "ID of the NAPI instance."]
10718    Id(u32),
10719}
10720impl<'a> IterableOpNapiGetDoRequest<'a> {
10721    #[doc = "ID of the NAPI instance."]
10722    pub fn get_id(&self) -> Result<u32, ErrorContext> {
10723        let mut iter = self.clone();
10724        iter.pos = 0;
10725        for attr in iter {
10726            if let OpNapiGetDoRequest::Id(val) = attr? {
10727                return Ok(val);
10728            }
10729        }
10730        Err(ErrorContext::new_missing(
10731            "OpNapiGetDoRequest",
10732            "Id",
10733            self.orig_loc,
10734            self.buf.as_ptr() as usize,
10735        ))
10736    }
10737}
10738impl OpNapiGetDoRequest {
10739    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoRequest<'a> {
10740        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10741        IterableOpNapiGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
10742    }
10743    fn attr_from_type(r#type: u16) -> Option<&'static str> {
10744        Napi::attr_from_type(r#type)
10745    }
10746}
10747#[derive(Clone, Copy, Default)]
10748pub struct IterableOpNapiGetDoRequest<'a> {
10749    buf: &'a [u8],
10750    pos: usize,
10751    orig_loc: usize,
10752}
10753impl<'a> IterableOpNapiGetDoRequest<'a> {
10754    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10755        Self {
10756            buf,
10757            pos: 0,
10758            orig_loc,
10759        }
10760    }
10761    pub fn get_buf(&self) -> &'a [u8] {
10762        self.buf
10763    }
10764}
10765impl<'a> Iterator for IterableOpNapiGetDoRequest<'a> {
10766    type Item = Result<OpNapiGetDoRequest, ErrorContext>;
10767    fn next(&mut self) -> Option<Self::Item> {
10768        if self.buf.len() == self.pos {
10769            return None;
10770        }
10771        let pos = self.pos;
10772        let mut r#type = None;
10773        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10774            r#type = Some(header.r#type);
10775            let res = match header.r#type {
10776                2u16 => OpNapiGetDoRequest::Id({
10777                    let res = parse_u32(next);
10778                    let Some(val) = res else { break };
10779                    val
10780                }),
10781                n => {
10782                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
10783                        break;
10784                    } else {
10785                        continue;
10786                    }
10787                }
10788            };
10789            return Some(Ok(res));
10790        }
10791        Some(Err(ErrorContext::new(
10792            "OpNapiGetDoRequest",
10793            r#type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10794            self.orig_loc,
10795            self.buf.as_ptr().wrapping_add(pos) as usize,
10796        )))
10797    }
10798}
10799impl std::fmt::Debug for IterableOpNapiGetDoRequest<'_> {
10800    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10801        let mut fmt = f.debug_struct("OpNapiGetDoRequest");
10802        for attr in self.clone() {
10803            let attr = match attr {
10804                Ok(a) => a,
10805                Err(err) => {
10806                    fmt.finish()?;
10807                    f.write_str("Err(")?;
10808                    err.fmt(f)?;
10809                    return f.write_str(")");
10810                }
10811            };
10812            match attr {
10813                OpNapiGetDoRequest::Id(val) => fmt.field("Id", &val),
10814            };
10815        }
10816        fmt.finish()
10817    }
10818}
10819impl IterableOpNapiGetDoRequest<'_> {
10820    pub fn lookup_attr(
10821        &self,
10822        offset: usize,
10823        missing_type: Option<u16>,
10824    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10825        let mut stack = Vec::new();
10826        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10827        if cur == offset + PushBuiltinNfgenmsg::len() {
10828            stack.push(("OpNapiGetDoRequest", offset));
10829            return (
10830                stack,
10831                missing_type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10832            );
10833        }
10834        if cur > offset || cur + self.buf.len() < offset {
10835            return (stack, None);
10836        }
10837        let mut attrs = self.clone();
10838        let mut last_off = cur + attrs.pos;
10839        while let Some(attr) = attrs.next() {
10840            let Ok(attr) = attr else { break };
10841            match attr {
10842                OpNapiGetDoRequest::Id(val) => {
10843                    if last_off == offset {
10844                        stack.push(("Id", last_off));
10845                        break;
10846                    }
10847                }
10848                _ => {}
10849            };
10850            last_off = cur + attrs.pos;
10851        }
10852        if !stack.is_empty() {
10853            stack.push(("OpNapiGetDoRequest", cur));
10854        }
10855        (stack, None)
10856    }
10857}
10858#[doc = "Get information about NAPI instances configured on the system."]
10859pub struct PushOpNapiGetDoReply<Prev: Rec> {
10860    pub(crate) prev: Option<Prev>,
10861    pub(crate) header_offset: Option<usize>,
10862}
10863impl<Prev: Rec> Rec for PushOpNapiGetDoReply<Prev> {
10864    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10865        self.prev.as_mut().unwrap().as_rec_mut()
10866    }
10867}
10868impl<Prev: Rec> PushOpNapiGetDoReply<Prev> {
10869    pub fn new(mut prev: Prev) -> Self {
10870        Self::write_header(&mut prev);
10871        Self::new_without_header(prev)
10872    }
10873    fn new_without_header(prev: Prev) -> Self {
10874        Self {
10875            prev: Some(prev),
10876            header_offset: None,
10877        }
10878    }
10879    fn write_header(prev: &mut Prev) {
10880        let mut header = PushBuiltinNfgenmsg::new();
10881        header.set_cmd(11u8);
10882        header.set_version(1u8);
10883        prev.as_rec_mut().extend(header.as_slice());
10884    }
10885    pub fn end_nested(mut self) -> Prev {
10886        let mut prev = self.prev.take().unwrap();
10887        if let Some(header_offset) = &self.header_offset {
10888            finalize_nested_header(prev.as_rec_mut(), *header_offset);
10889        }
10890        prev
10891    }
10892    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10893    pub fn push_ifindex(mut self, value: u32) -> Self {
10894        push_header(self.as_rec_mut(), 1u16, 4 as u16);
10895        self.as_rec_mut().extend(value.to_ne_bytes());
10896        self
10897    }
10898    #[doc = "ID of the NAPI instance."]
10899    pub fn push_id(mut self, value: u32) -> Self {
10900        push_header(self.as_rec_mut(), 2u16, 4 as u16);
10901        self.as_rec_mut().extend(value.to_ne_bytes());
10902        self
10903    }
10904    #[doc = "The associated interrupt vector number for the napi"]
10905    pub fn push_irq(mut self, value: u32) -> Self {
10906        push_header(self.as_rec_mut(), 3u16, 4 as u16);
10907        self.as_rec_mut().extend(value.to_ne_bytes());
10908        self
10909    }
10910    #[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."]
10911    pub fn push_pid(mut self, value: u32) -> Self {
10912        push_header(self.as_rec_mut(), 4u16, 4 as u16);
10913        self.as_rec_mut().extend(value.to_ne_bytes());
10914        self
10915    }
10916    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10917    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10918        push_header(self.as_rec_mut(), 5u16, 4 as u16);
10919        self.as_rec_mut().extend(value.to_ne_bytes());
10920        self
10921    }
10922    #[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."]
10923    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10924        push_header(self.as_rec_mut(), 6u16, 4 as u16);
10925        self.as_rec_mut().extend(value.to_ne_bytes());
10926        self
10927    }
10928    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10929    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10930        push_header(self.as_rec_mut(), 7u16, 4 as u16);
10931        self.as_rec_mut().extend(value.to_ne_bytes());
10932        self
10933    }
10934    #[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)"]
10935    pub fn push_threaded(mut self, value: u32) -> Self {
10936        push_header(self.as_rec_mut(), 8u16, 4 as u16);
10937        self.as_rec_mut().extend(value.to_ne_bytes());
10938        self
10939    }
10940}
10941impl<Prev: Rec> Drop for PushOpNapiGetDoReply<Prev> {
10942    fn drop(&mut self) {
10943        if let Some(prev) = &mut self.prev {
10944            if let Some(header_offset) = &self.header_offset {
10945                finalize_nested_header(prev.as_rec_mut(), *header_offset);
10946            }
10947        }
10948    }
10949}
10950#[doc = "Get information about NAPI instances configured on the system."]
10951#[derive(Clone)]
10952pub enum OpNapiGetDoReply {
10953    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10954    Ifindex(u32),
10955    #[doc = "ID of the NAPI instance."]
10956    Id(u32),
10957    #[doc = "The associated interrupt vector number for the napi"]
10958    Irq(u32),
10959    #[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."]
10960    Pid(u32),
10961    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10962    DeferHardIrqs(u32),
10963    #[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."]
10964    GroFlushTimeout(u32),
10965    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10966    IrqSuspendTimeout(u32),
10967    #[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)"]
10968    Threaded(u32),
10969}
10970impl<'a> IterableOpNapiGetDoReply<'a> {
10971    #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10972    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10973        let mut iter = self.clone();
10974        iter.pos = 0;
10975        for attr in iter {
10976            if let OpNapiGetDoReply::Ifindex(val) = attr? {
10977                return Ok(val);
10978            }
10979        }
10980        Err(ErrorContext::new_missing(
10981            "OpNapiGetDoReply",
10982            "Ifindex",
10983            self.orig_loc,
10984            self.buf.as_ptr() as usize,
10985        ))
10986    }
10987    #[doc = "ID of the NAPI instance."]
10988    pub fn get_id(&self) -> Result<u32, ErrorContext> {
10989        let mut iter = self.clone();
10990        iter.pos = 0;
10991        for attr in iter {
10992            if let OpNapiGetDoReply::Id(val) = attr? {
10993                return Ok(val);
10994            }
10995        }
10996        Err(ErrorContext::new_missing(
10997            "OpNapiGetDoReply",
10998            "Id",
10999            self.orig_loc,
11000            self.buf.as_ptr() as usize,
11001        ))
11002    }
11003    #[doc = "The associated interrupt vector number for the napi"]
11004    pub fn get_irq(&self) -> Result<u32, ErrorContext> {
11005        let mut iter = self.clone();
11006        iter.pos = 0;
11007        for attr in iter {
11008            if let OpNapiGetDoReply::Irq(val) = attr? {
11009                return Ok(val);
11010            }
11011        }
11012        Err(ErrorContext::new_missing(
11013            "OpNapiGetDoReply",
11014            "Irq",
11015            self.orig_loc,
11016            self.buf.as_ptr() as usize,
11017        ))
11018    }
11019    #[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."]
11020    pub fn get_pid(&self) -> Result<u32, ErrorContext> {
11021        let mut iter = self.clone();
11022        iter.pos = 0;
11023        for attr in iter {
11024            if let OpNapiGetDoReply::Pid(val) = attr? {
11025                return Ok(val);
11026            }
11027        }
11028        Err(ErrorContext::new_missing(
11029            "OpNapiGetDoReply",
11030            "Pid",
11031            self.orig_loc,
11032            self.buf.as_ptr() as usize,
11033        ))
11034    }
11035    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11036    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
11037        let mut iter = self.clone();
11038        iter.pos = 0;
11039        for attr in iter {
11040            if let OpNapiGetDoReply::DeferHardIrqs(val) = attr? {
11041                return Ok(val);
11042            }
11043        }
11044        Err(ErrorContext::new_missing(
11045            "OpNapiGetDoReply",
11046            "DeferHardIrqs",
11047            self.orig_loc,
11048            self.buf.as_ptr() as usize,
11049        ))
11050    }
11051    #[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."]
11052    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
11053        let mut iter = self.clone();
11054        iter.pos = 0;
11055        for attr in iter {
11056            if let OpNapiGetDoReply::GroFlushTimeout(val) = attr? {
11057                return Ok(val);
11058            }
11059        }
11060        Err(ErrorContext::new_missing(
11061            "OpNapiGetDoReply",
11062            "GroFlushTimeout",
11063            self.orig_loc,
11064            self.buf.as_ptr() as usize,
11065        ))
11066    }
11067    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11068    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
11069        let mut iter = self.clone();
11070        iter.pos = 0;
11071        for attr in iter {
11072            if let OpNapiGetDoReply::IrqSuspendTimeout(val) = attr? {
11073                return Ok(val);
11074            }
11075        }
11076        Err(ErrorContext::new_missing(
11077            "OpNapiGetDoReply",
11078            "IrqSuspendTimeout",
11079            self.orig_loc,
11080            self.buf.as_ptr() as usize,
11081        ))
11082    }
11083    #[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)"]
11084    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
11085        let mut iter = self.clone();
11086        iter.pos = 0;
11087        for attr in iter {
11088            if let OpNapiGetDoReply::Threaded(val) = attr? {
11089                return Ok(val);
11090            }
11091        }
11092        Err(ErrorContext::new_missing(
11093            "OpNapiGetDoReply",
11094            "Threaded",
11095            self.orig_loc,
11096            self.buf.as_ptr() as usize,
11097        ))
11098    }
11099}
11100impl OpNapiGetDoReply {
11101    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoReply<'a> {
11102        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11103        IterableOpNapiGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
11104    }
11105    fn attr_from_type(r#type: u16) -> Option<&'static str> {
11106        Napi::attr_from_type(r#type)
11107    }
11108}
11109#[derive(Clone, Copy, Default)]
11110pub struct IterableOpNapiGetDoReply<'a> {
11111    buf: &'a [u8],
11112    pos: usize,
11113    orig_loc: usize,
11114}
11115impl<'a> IterableOpNapiGetDoReply<'a> {
11116    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11117        Self {
11118            buf,
11119            pos: 0,
11120            orig_loc,
11121        }
11122    }
11123    pub fn get_buf(&self) -> &'a [u8] {
11124        self.buf
11125    }
11126}
11127impl<'a> Iterator for IterableOpNapiGetDoReply<'a> {
11128    type Item = Result<OpNapiGetDoReply, ErrorContext>;
11129    fn next(&mut self) -> Option<Self::Item> {
11130        if self.buf.len() == self.pos {
11131            return None;
11132        }
11133        let pos = self.pos;
11134        let mut r#type = None;
11135        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
11136            r#type = Some(header.r#type);
11137            let res = match header.r#type {
11138                1u16 => OpNapiGetDoReply::Ifindex({
11139                    let res = parse_u32(next);
11140                    let Some(val) = res else { break };
11141                    val
11142                }),
11143                2u16 => OpNapiGetDoReply::Id({
11144                    let res = parse_u32(next);
11145                    let Some(val) = res else { break };
11146                    val
11147                }),
11148                3u16 => OpNapiGetDoReply::Irq({
11149                    let res = parse_u32(next);
11150                    let Some(val) = res else { break };
11151                    val
11152                }),
11153                4u16 => OpNapiGetDoReply::Pid({
11154                    let res = parse_u32(next);
11155                    let Some(val) = res else { break };
11156                    val
11157                }),
11158                5u16 => OpNapiGetDoReply::DeferHardIrqs({
11159                    let res = parse_u32(next);
11160                    let Some(val) = res else { break };
11161                    val
11162                }),
11163                6u16 => OpNapiGetDoReply::GroFlushTimeout({
11164                    let res = parse_u32(next);
11165                    let Some(val) = res else { break };
11166                    val
11167                }),
11168                7u16 => OpNapiGetDoReply::IrqSuspendTimeout({
11169                    let res = parse_u32(next);
11170                    let Some(val) = res else { break };
11171                    val
11172                }),
11173                8u16 => OpNapiGetDoReply::Threaded({
11174                    let res = parse_u32(next);
11175                    let Some(val) = res else { break };
11176                    val
11177                }),
11178                n => {
11179                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
11180                        break;
11181                    } else {
11182                        continue;
11183                    }
11184                }
11185            };
11186            return Some(Ok(res));
11187        }
11188        Some(Err(ErrorContext::new(
11189            "OpNapiGetDoReply",
11190            r#type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11191            self.orig_loc,
11192            self.buf.as_ptr().wrapping_add(pos) as usize,
11193        )))
11194    }
11195}
11196impl std::fmt::Debug for IterableOpNapiGetDoReply<'_> {
11197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11198        let mut fmt = f.debug_struct("OpNapiGetDoReply");
11199        for attr in self.clone() {
11200            let attr = match attr {
11201                Ok(a) => a,
11202                Err(err) => {
11203                    fmt.finish()?;
11204                    f.write_str("Err(")?;
11205                    err.fmt(f)?;
11206                    return f.write_str(")");
11207                }
11208            };
11209            match attr {
11210                OpNapiGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
11211                OpNapiGetDoReply::Id(val) => fmt.field("Id", &val),
11212                OpNapiGetDoReply::Irq(val) => fmt.field("Irq", &val),
11213                OpNapiGetDoReply::Pid(val) => fmt.field("Pid", &val),
11214                OpNapiGetDoReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
11215                OpNapiGetDoReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
11216                OpNapiGetDoReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
11217                OpNapiGetDoReply::Threaded(val) => fmt.field(
11218                    "Threaded",
11219                    &FormatEnum(val.into(), NapiThreaded::from_value),
11220                ),
11221            };
11222        }
11223        fmt.finish()
11224    }
11225}
11226impl IterableOpNapiGetDoReply<'_> {
11227    pub fn lookup_attr(
11228        &self,
11229        offset: usize,
11230        missing_type: Option<u16>,
11231    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11232        let mut stack = Vec::new();
11233        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11234        if cur == offset + PushBuiltinNfgenmsg::len() {
11235            stack.push(("OpNapiGetDoReply", offset));
11236            return (
11237                stack,
11238                missing_type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11239            );
11240        }
11241        if cur > offset || cur + self.buf.len() < offset {
11242            return (stack, None);
11243        }
11244        let mut attrs = self.clone();
11245        let mut last_off = cur + attrs.pos;
11246        while let Some(attr) = attrs.next() {
11247            let Ok(attr) = attr else { break };
11248            match attr {
11249                OpNapiGetDoReply::Ifindex(val) => {
11250                    if last_off == offset {
11251                        stack.push(("Ifindex", last_off));
11252                        break;
11253                    }
11254                }
11255                OpNapiGetDoReply::Id(val) => {
11256                    if last_off == offset {
11257                        stack.push(("Id", last_off));
11258                        break;
11259                    }
11260                }
11261                OpNapiGetDoReply::Irq(val) => {
11262                    if last_off == offset {
11263                        stack.push(("Irq", last_off));
11264                        break;
11265                    }
11266                }
11267                OpNapiGetDoReply::Pid(val) => {
11268                    if last_off == offset {
11269                        stack.push(("Pid", last_off));
11270                        break;
11271                    }
11272                }
11273                OpNapiGetDoReply::DeferHardIrqs(val) => {
11274                    if last_off == offset {
11275                        stack.push(("DeferHardIrqs", last_off));
11276                        break;
11277                    }
11278                }
11279                OpNapiGetDoReply::GroFlushTimeout(val) => {
11280                    if last_off == offset {
11281                        stack.push(("GroFlushTimeout", last_off));
11282                        break;
11283                    }
11284                }
11285                OpNapiGetDoReply::IrqSuspendTimeout(val) => {
11286                    if last_off == offset {
11287                        stack.push(("IrqSuspendTimeout", last_off));
11288                        break;
11289                    }
11290                }
11291                OpNapiGetDoReply::Threaded(val) => {
11292                    if last_off == offset {
11293                        stack.push(("Threaded", last_off));
11294                        break;
11295                    }
11296                }
11297                _ => {}
11298            };
11299            last_off = cur + attrs.pos;
11300        }
11301        if !stack.is_empty() {
11302            stack.push(("OpNapiGetDoReply", cur));
11303        }
11304        (stack, None)
11305    }
11306}
11307#[derive(Debug)]
11308pub struct RequestOpNapiGetDoRequest<'r> {
11309    request: Request<'r>,
11310}
11311impl<'r> RequestOpNapiGetDoRequest<'r> {
11312    pub fn new(mut request: Request<'r>) -> Self {
11313        PushOpNapiGetDoRequest::write_header(&mut request.buf_mut());
11314        Self { request: request }
11315    }
11316    pub fn encode(&mut self) -> PushOpNapiGetDoRequest<&mut Vec<u8>> {
11317        PushOpNapiGetDoRequest::new_without_header(self.request.buf_mut())
11318    }
11319    pub fn into_encoder(self) -> PushOpNapiGetDoRequest<RequestBuf<'r>> {
11320        PushOpNapiGetDoRequest::new_without_header(self.request.buf)
11321    }
11322}
11323impl NetlinkRequest for RequestOpNapiGetDoRequest<'_> {
11324    type ReplyType<'buf> = IterableOpNapiGetDoReply<'buf>;
11325    fn protocol(&self) -> Protocol {
11326        Protocol::Generic("netdev".as_bytes())
11327    }
11328    fn flags(&self) -> u16 {
11329        self.request.flags
11330    }
11331    fn payload(&self) -> &[u8] {
11332        self.request.buf()
11333    }
11334    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
11335        OpNapiGetDoReply::new(buf)
11336    }
11337    fn lookup(
11338        buf: &[u8],
11339        offset: usize,
11340        missing_type: Option<u16>,
11341    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11342        OpNapiGetDoRequest::new(buf).lookup_attr(offset, missing_type)
11343    }
11344}
11345#[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"]
11346pub struct PushOpQstatsGetDumpRequest<Prev: Rec> {
11347    pub(crate) prev: Option<Prev>,
11348    pub(crate) header_offset: Option<usize>,
11349}
11350impl<Prev: Rec> Rec for PushOpQstatsGetDumpRequest<Prev> {
11351    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11352        self.prev.as_mut().unwrap().as_rec_mut()
11353    }
11354}
11355impl<Prev: Rec> PushOpQstatsGetDumpRequest<Prev> {
11356    pub fn new(mut prev: Prev) -> Self {
11357        Self::write_header(&mut prev);
11358        Self::new_without_header(prev)
11359    }
11360    fn new_without_header(prev: Prev) -> Self {
11361        Self {
11362            prev: Some(prev),
11363            header_offset: None,
11364        }
11365    }
11366    fn write_header(prev: &mut Prev) {
11367        let mut header = PushBuiltinNfgenmsg::new();
11368        header.set_cmd(12u8);
11369        header.set_version(1u8);
11370        prev.as_rec_mut().extend(header.as_slice());
11371    }
11372    pub fn end_nested(mut self) -> Prev {
11373        let mut prev = self.prev.take().unwrap();
11374        if let Some(header_offset) = &self.header_offset {
11375            finalize_nested_header(prev.as_rec_mut(), *header_offset);
11376        }
11377        prev
11378    }
11379    #[doc = "ifindex of the netdevice to which stats belong."]
11380    pub fn push_ifindex(mut self, value: u32) -> Self {
11381        push_header(self.as_rec_mut(), 1u16, 4 as u16);
11382        self.as_rec_mut().extend(value.to_ne_bytes());
11383        self
11384    }
11385    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11386    pub fn push_scope(mut self, value: u32) -> Self {
11387        push_header(self.as_rec_mut(), 4u16, 4 as u16);
11388        self.as_rec_mut().extend(value.to_ne_bytes());
11389        self
11390    }
11391}
11392impl<Prev: Rec> Drop for PushOpQstatsGetDumpRequest<Prev> {
11393    fn drop(&mut self) {
11394        if let Some(prev) = &mut self.prev {
11395            if let Some(header_offset) = &self.header_offset {
11396                finalize_nested_header(prev.as_rec_mut(), *header_offset);
11397            }
11398        }
11399    }
11400}
11401#[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"]
11402#[derive(Clone)]
11403pub enum OpQstatsGetDumpRequest {
11404    #[doc = "ifindex of the netdevice to which stats belong."]
11405    Ifindex(u32),
11406    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11407    Scope(u32),
11408}
11409impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11410    #[doc = "ifindex of the netdevice to which stats belong."]
11411    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11412        let mut iter = self.clone();
11413        iter.pos = 0;
11414        for attr in iter {
11415            if let OpQstatsGetDumpRequest::Ifindex(val) = attr? {
11416                return Ok(val);
11417            }
11418        }
11419        Err(ErrorContext::new_missing(
11420            "OpQstatsGetDumpRequest",
11421            "Ifindex",
11422            self.orig_loc,
11423            self.buf.as_ptr() as usize,
11424        ))
11425    }
11426    #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11427    pub fn get_scope(&self) -> Result<u32, ErrorContext> {
11428        let mut iter = self.clone();
11429        iter.pos = 0;
11430        for attr in iter {
11431            if let OpQstatsGetDumpRequest::Scope(val) = attr? {
11432                return Ok(val);
11433            }
11434        }
11435        Err(ErrorContext::new_missing(
11436            "OpQstatsGetDumpRequest",
11437            "Scope",
11438            self.orig_loc,
11439            self.buf.as_ptr() as usize,
11440        ))
11441    }
11442}
11443impl OpQstatsGetDumpRequest {
11444    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpRequest<'a> {
11445        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11446        IterableOpQstatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
11447    }
11448    fn attr_from_type(r#type: u16) -> Option<&'static str> {
11449        Qstats::attr_from_type(r#type)
11450    }
11451}
11452#[derive(Clone, Copy, Default)]
11453pub struct IterableOpQstatsGetDumpRequest<'a> {
11454    buf: &'a [u8],
11455    pos: usize,
11456    orig_loc: usize,
11457}
11458impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11459    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11460        Self {
11461            buf,
11462            pos: 0,
11463            orig_loc,
11464        }
11465    }
11466    pub fn get_buf(&self) -> &'a [u8] {
11467        self.buf
11468    }
11469}
11470impl<'a> Iterator for IterableOpQstatsGetDumpRequest<'a> {
11471    type Item = Result<OpQstatsGetDumpRequest, ErrorContext>;
11472    fn next(&mut self) -> Option<Self::Item> {
11473        if self.buf.len() == self.pos {
11474            return None;
11475        }
11476        let pos = self.pos;
11477        let mut r#type = None;
11478        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
11479            r#type = Some(header.r#type);
11480            let res = match header.r#type {
11481                1u16 => OpQstatsGetDumpRequest::Ifindex({
11482                    let res = parse_u32(next);
11483                    let Some(val) = res else { break };
11484                    val
11485                }),
11486                4u16 => OpQstatsGetDumpRequest::Scope({
11487                    let res = parse_u32(next);
11488                    let Some(val) = res else { break };
11489                    val
11490                }),
11491                n => {
11492                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
11493                        break;
11494                    } else {
11495                        continue;
11496                    }
11497                }
11498            };
11499            return Some(Ok(res));
11500        }
11501        Some(Err(ErrorContext::new(
11502            "OpQstatsGetDumpRequest",
11503            r#type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11504            self.orig_loc,
11505            self.buf.as_ptr().wrapping_add(pos) as usize,
11506        )))
11507    }
11508}
11509impl std::fmt::Debug for IterableOpQstatsGetDumpRequest<'_> {
11510    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11511        let mut fmt = f.debug_struct("OpQstatsGetDumpRequest");
11512        for attr in self.clone() {
11513            let attr = match attr {
11514                Ok(a) => a,
11515                Err(err) => {
11516                    fmt.finish()?;
11517                    f.write_str("Err(")?;
11518                    err.fmt(f)?;
11519                    return f.write_str(")");
11520                }
11521            };
11522            match attr {
11523                OpQstatsGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
11524                OpQstatsGetDumpRequest::Scope(val) => {
11525                    fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
11526                }
11527            };
11528        }
11529        fmt.finish()
11530    }
11531}
11532impl IterableOpQstatsGetDumpRequest<'_> {
11533    pub fn lookup_attr(
11534        &self,
11535        offset: usize,
11536        missing_type: Option<u16>,
11537    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11538        let mut stack = Vec::new();
11539        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11540        if cur == offset + PushBuiltinNfgenmsg::len() {
11541            stack.push(("OpQstatsGetDumpRequest", offset));
11542            return (
11543                stack,
11544                missing_type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11545            );
11546        }
11547        if cur > offset || cur + self.buf.len() < offset {
11548            return (stack, None);
11549        }
11550        let mut attrs = self.clone();
11551        let mut last_off = cur + attrs.pos;
11552        while let Some(attr) = attrs.next() {
11553            let Ok(attr) = attr else { break };
11554            match attr {
11555                OpQstatsGetDumpRequest::Ifindex(val) => {
11556                    if last_off == offset {
11557                        stack.push(("Ifindex", last_off));
11558                        break;
11559                    }
11560                }
11561                OpQstatsGetDumpRequest::Scope(val) => {
11562                    if last_off == offset {
11563                        stack.push(("Scope", last_off));
11564                        break;
11565                    }
11566                }
11567                _ => {}
11568            };
11569            last_off = cur + attrs.pos;
11570        }
11571        if !stack.is_empty() {
11572            stack.push(("OpQstatsGetDumpRequest", cur));
11573        }
11574        (stack, None)
11575    }
11576}
11577#[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"]
11578pub struct PushOpQstatsGetDumpReply<Prev: Rec> {
11579    pub(crate) prev: Option<Prev>,
11580    pub(crate) header_offset: Option<usize>,
11581}
11582impl<Prev: Rec> Rec for PushOpQstatsGetDumpReply<Prev> {
11583    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11584        self.prev.as_mut().unwrap().as_rec_mut()
11585    }
11586}
11587impl<Prev: Rec> PushOpQstatsGetDumpReply<Prev> {
11588    pub fn new(mut prev: Prev) -> Self {
11589        Self::write_header(&mut prev);
11590        Self::new_without_header(prev)
11591    }
11592    fn new_without_header(prev: Prev) -> Self {
11593        Self {
11594            prev: Some(prev),
11595            header_offset: None,
11596        }
11597    }
11598    fn write_header(prev: &mut Prev) {
11599        let mut header = PushBuiltinNfgenmsg::new();
11600        header.set_cmd(12u8);
11601        header.set_version(1u8);
11602        prev.as_rec_mut().extend(header.as_slice());
11603    }
11604    pub fn end_nested(mut self) -> Prev {
11605        let mut prev = self.prev.take().unwrap();
11606        if let Some(header_offset) = &self.header_offset {
11607            finalize_nested_header(prev.as_rec_mut(), *header_offset);
11608        }
11609        prev
11610    }
11611    #[doc = "ifindex of the netdevice to which stats belong."]
11612    pub fn push_ifindex(mut self, value: u32) -> Self {
11613        push_header(self.as_rec_mut(), 1u16, 4 as u16);
11614        self.as_rec_mut().extend(value.to_ne_bytes());
11615        self
11616    }
11617    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11618    pub fn push_queue_type(mut self, value: u32) -> Self {
11619        push_header(self.as_rec_mut(), 2u16, 4 as u16);
11620        self.as_rec_mut().extend(value.to_ne_bytes());
11621        self
11622    }
11623    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11624    pub fn push_queue_id(mut self, value: u32) -> Self {
11625        push_header(self.as_rec_mut(), 3u16, 4 as u16);
11626        self.as_rec_mut().extend(value.to_ne_bytes());
11627        self
11628    }
11629    #[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"]
11630    pub fn push_rx_packets(mut self, value: u32) -> Self {
11631        push_header(self.as_rec_mut(), 8u16, 4 as u16);
11632        self.as_rec_mut().extend(value.to_ne_bytes());
11633        self
11634    }
11635    #[doc = "Successfully received bytes, see `rx-packets`."]
11636    pub fn push_rx_bytes(mut self, value: u32) -> Self {
11637        push_header(self.as_rec_mut(), 9u16, 4 as u16);
11638        self.as_rec_mut().extend(value.to_ne_bytes());
11639        self
11640    }
11641    #[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"]
11642    pub fn push_tx_packets(mut self, value: u32) -> Self {
11643        push_header(self.as_rec_mut(), 10u16, 4 as u16);
11644        self.as_rec_mut().extend(value.to_ne_bytes());
11645        self
11646    }
11647    #[doc = "Successfully sent bytes, see `tx-packets`."]
11648    pub fn push_tx_bytes(mut self, value: u32) -> Self {
11649        push_header(self.as_rec_mut(), 11u16, 4 as u16);
11650        self.as_rec_mut().extend(value.to_ne_bytes());
11651        self
11652    }
11653    #[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"]
11654    pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
11655        push_header(self.as_rec_mut(), 12u16, 4 as u16);
11656        self.as_rec_mut().extend(value.to_ne_bytes());
11657        self
11658    }
11659    #[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"]
11660    pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
11661        push_header(self.as_rec_mut(), 13u16, 4 as u16);
11662        self.as_rec_mut().extend(value.to_ne_bytes());
11663        self
11664    }
11665    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11666    pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
11667        push_header(self.as_rec_mut(), 14u16, 4 as u16);
11668        self.as_rec_mut().extend(value.to_ne_bytes());
11669        self
11670    }
11671    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11672    pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
11673        push_header(self.as_rec_mut(), 15u16, 4 as u16);
11674        self.as_rec_mut().extend(value.to_ne_bytes());
11675        self
11676    }
11677    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11678    pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
11679        push_header(self.as_rec_mut(), 16u16, 4 as u16);
11680        self.as_rec_mut().extend(value.to_ne_bytes());
11681        self
11682    }
11683    #[doc = "Number of packets that were not checksummed by device."]
11684    pub fn push_rx_csum_none(mut self, value: u32) -> Self {
11685        push_header(self.as_rec_mut(), 17u16, 4 as u16);
11686        self.as_rec_mut().extend(value.to_ne_bytes());
11687        self
11688    }
11689    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11690    pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
11691        push_header(self.as_rec_mut(), 18u16, 4 as u16);
11692        self.as_rec_mut().extend(value.to_ne_bytes());
11693        self
11694    }
11695    #[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"]
11696    pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
11697        push_header(self.as_rec_mut(), 19u16, 4 as u16);
11698        self.as_rec_mut().extend(value.to_ne_bytes());
11699        self
11700    }
11701    #[doc = "See `rx-hw-gro-packets`."]
11702    pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
11703        push_header(self.as_rec_mut(), 20u16, 4 as u16);
11704        self.as_rec_mut().extend(value.to_ne_bytes());
11705        self
11706    }
11707    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11708    pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
11709        push_header(self.as_rec_mut(), 21u16, 4 as u16);
11710        self.as_rec_mut().extend(value.to_ne_bytes());
11711        self
11712    }
11713    #[doc = "See `rx-hw-gro-wire-packets`."]
11714    pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
11715        push_header(self.as_rec_mut(), 22u16, 4 as u16);
11716        self.as_rec_mut().extend(value.to_ne_bytes());
11717        self
11718    }
11719    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11720    pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11721        push_header(self.as_rec_mut(), 23u16, 4 as u16);
11722        self.as_rec_mut().extend(value.to_ne_bytes());
11723        self
11724    }
11725    #[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"]
11726    pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
11727        push_header(self.as_rec_mut(), 24u16, 4 as u16);
11728        self.as_rec_mut().extend(value.to_ne_bytes());
11729        self
11730    }
11731    #[doc = "Number of packets dropped because they were invalid or malformed."]
11732    pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
11733        push_header(self.as_rec_mut(), 25u16, 4 as u16);
11734        self.as_rec_mut().extend(value.to_ne_bytes());
11735        self
11736    }
11737    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11738    pub fn push_tx_csum_none(mut self, value: u32) -> Self {
11739        push_header(self.as_rec_mut(), 26u16, 4 as u16);
11740        self.as_rec_mut().extend(value.to_ne_bytes());
11741        self
11742    }
11743    #[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"]
11744    pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
11745        push_header(self.as_rec_mut(), 27u16, 4 as u16);
11746        self.as_rec_mut().extend(value.to_ne_bytes());
11747        self
11748    }
11749    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11750    pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
11751        push_header(self.as_rec_mut(), 28u16, 4 as u16);
11752        self.as_rec_mut().extend(value.to_ne_bytes());
11753        self
11754    }
11755    #[doc = "See `tx-hw-gso-packets`."]
11756    pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
11757        push_header(self.as_rec_mut(), 29u16, 4 as u16);
11758        self.as_rec_mut().extend(value.to_ne_bytes());
11759        self
11760    }
11761    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11762    pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
11763        push_header(self.as_rec_mut(), 30u16, 4 as u16);
11764        self.as_rec_mut().extend(value.to_ne_bytes());
11765        self
11766    }
11767    #[doc = "See `tx-hw-gso-wire-packets`."]
11768    pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
11769        push_header(self.as_rec_mut(), 31u16, 4 as u16);
11770        self.as_rec_mut().extend(value.to_ne_bytes());
11771        self
11772    }
11773    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11774    pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11775        push_header(self.as_rec_mut(), 32u16, 4 as u16);
11776        self.as_rec_mut().extend(value.to_ne_bytes());
11777        self
11778    }
11779    #[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"]
11780    pub fn push_tx_stop(mut self, value: u32) -> Self {
11781        push_header(self.as_rec_mut(), 33u16, 4 as u16);
11782        self.as_rec_mut().extend(value.to_ne_bytes());
11783        self
11784    }
11785    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11786    pub fn push_tx_wake(mut self, value: u32) -> Self {
11787        push_header(self.as_rec_mut(), 34u16, 4 as u16);
11788        self.as_rec_mut().extend(value.to_ne_bytes());
11789        self
11790    }
11791}
11792impl<Prev: Rec> Drop for PushOpQstatsGetDumpReply<Prev> {
11793    fn drop(&mut self) {
11794        if let Some(prev) = &mut self.prev {
11795            if let Some(header_offset) = &self.header_offset {
11796                finalize_nested_header(prev.as_rec_mut(), *header_offset);
11797            }
11798        }
11799    }
11800}
11801#[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"]
11802#[derive(Clone)]
11803pub enum OpQstatsGetDumpReply {
11804    #[doc = "ifindex of the netdevice to which stats belong."]
11805    Ifindex(u32),
11806    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11807    QueueType(u32),
11808    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11809    QueueId(u32),
11810    #[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"]
11811    RxPackets(u32),
11812    #[doc = "Successfully received bytes, see `rx-packets`."]
11813    RxBytes(u32),
11814    #[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"]
11815    TxPackets(u32),
11816    #[doc = "Successfully sent bytes, see `tx-packets`."]
11817    TxBytes(u32),
11818    #[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"]
11819    RxAllocFail(u32),
11820    #[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"]
11821    RxHwDrops(u32),
11822    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11823    RxHwDropOverruns(u32),
11824    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11825    RxCsumComplete(u32),
11826    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11827    RxCsumUnnecessary(u32),
11828    #[doc = "Number of packets that were not checksummed by device."]
11829    RxCsumNone(u32),
11830    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11831    RxCsumBad(u32),
11832    #[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"]
11833    RxHwGroPackets(u32),
11834    #[doc = "See `rx-hw-gro-packets`."]
11835    RxHwGroBytes(u32),
11836    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11837    RxHwGroWirePackets(u32),
11838    #[doc = "See `rx-hw-gro-wire-packets`."]
11839    RxHwGroWireBytes(u32),
11840    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11841    RxHwDropRatelimits(u32),
11842    #[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"]
11843    TxHwDrops(u32),
11844    #[doc = "Number of packets dropped because they were invalid or malformed."]
11845    TxHwDropErrors(u32),
11846    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11847    TxCsumNone(u32),
11848    #[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"]
11849    TxNeedsCsum(u32),
11850    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11851    TxHwGsoPackets(u32),
11852    #[doc = "See `tx-hw-gso-packets`."]
11853    TxHwGsoBytes(u32),
11854    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11855    TxHwGsoWirePackets(u32),
11856    #[doc = "See `tx-hw-gso-wire-packets`."]
11857    TxHwGsoWireBytes(u32),
11858    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11859    TxHwDropRatelimits(u32),
11860    #[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"]
11861    TxStop(u32),
11862    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11863    TxWake(u32),
11864}
11865impl<'a> IterableOpQstatsGetDumpReply<'a> {
11866    #[doc = "ifindex of the netdevice to which stats belong."]
11867    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11868        let mut iter = self.clone();
11869        iter.pos = 0;
11870        for attr in iter {
11871            if let OpQstatsGetDumpReply::Ifindex(val) = attr? {
11872                return Ok(val);
11873            }
11874        }
11875        Err(ErrorContext::new_missing(
11876            "OpQstatsGetDumpReply",
11877            "Ifindex",
11878            self.orig_loc,
11879            self.buf.as_ptr() as usize,
11880        ))
11881    }
11882    #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11883    pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
11884        let mut iter = self.clone();
11885        iter.pos = 0;
11886        for attr in iter {
11887            if let OpQstatsGetDumpReply::QueueType(val) = attr? {
11888                return Ok(val);
11889            }
11890        }
11891        Err(ErrorContext::new_missing(
11892            "OpQstatsGetDumpReply",
11893            "QueueType",
11894            self.orig_loc,
11895            self.buf.as_ptr() as usize,
11896        ))
11897    }
11898    #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11899    pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
11900        let mut iter = self.clone();
11901        iter.pos = 0;
11902        for attr in iter {
11903            if let OpQstatsGetDumpReply::QueueId(val) = attr? {
11904                return Ok(val);
11905            }
11906        }
11907        Err(ErrorContext::new_missing(
11908            "OpQstatsGetDumpReply",
11909            "QueueId",
11910            self.orig_loc,
11911            self.buf.as_ptr() as usize,
11912        ))
11913    }
11914    #[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"]
11915    pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
11916        let mut iter = self.clone();
11917        iter.pos = 0;
11918        for attr in iter {
11919            if let OpQstatsGetDumpReply::RxPackets(val) = attr? {
11920                return Ok(val);
11921            }
11922        }
11923        Err(ErrorContext::new_missing(
11924            "OpQstatsGetDumpReply",
11925            "RxPackets",
11926            self.orig_loc,
11927            self.buf.as_ptr() as usize,
11928        ))
11929    }
11930    #[doc = "Successfully received bytes, see `rx-packets`."]
11931    pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
11932        let mut iter = self.clone();
11933        iter.pos = 0;
11934        for attr in iter {
11935            if let OpQstatsGetDumpReply::RxBytes(val) = attr? {
11936                return Ok(val);
11937            }
11938        }
11939        Err(ErrorContext::new_missing(
11940            "OpQstatsGetDumpReply",
11941            "RxBytes",
11942            self.orig_loc,
11943            self.buf.as_ptr() as usize,
11944        ))
11945    }
11946    #[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"]
11947    pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
11948        let mut iter = self.clone();
11949        iter.pos = 0;
11950        for attr in iter {
11951            if let OpQstatsGetDumpReply::TxPackets(val) = attr? {
11952                return Ok(val);
11953            }
11954        }
11955        Err(ErrorContext::new_missing(
11956            "OpQstatsGetDumpReply",
11957            "TxPackets",
11958            self.orig_loc,
11959            self.buf.as_ptr() as usize,
11960        ))
11961    }
11962    #[doc = "Successfully sent bytes, see `tx-packets`."]
11963    pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
11964        let mut iter = self.clone();
11965        iter.pos = 0;
11966        for attr in iter {
11967            if let OpQstatsGetDumpReply::TxBytes(val) = attr? {
11968                return Ok(val);
11969            }
11970        }
11971        Err(ErrorContext::new_missing(
11972            "OpQstatsGetDumpReply",
11973            "TxBytes",
11974            self.orig_loc,
11975            self.buf.as_ptr() as usize,
11976        ))
11977    }
11978    #[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"]
11979    pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
11980        let mut iter = self.clone();
11981        iter.pos = 0;
11982        for attr in iter {
11983            if let OpQstatsGetDumpReply::RxAllocFail(val) = attr? {
11984                return Ok(val);
11985            }
11986        }
11987        Err(ErrorContext::new_missing(
11988            "OpQstatsGetDumpReply",
11989            "RxAllocFail",
11990            self.orig_loc,
11991            self.buf.as_ptr() as usize,
11992        ))
11993    }
11994    #[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"]
11995    pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
11996        let mut iter = self.clone();
11997        iter.pos = 0;
11998        for attr in iter {
11999            if let OpQstatsGetDumpReply::RxHwDrops(val) = attr? {
12000                return Ok(val);
12001            }
12002        }
12003        Err(ErrorContext::new_missing(
12004            "OpQstatsGetDumpReply",
12005            "RxHwDrops",
12006            self.orig_loc,
12007            self.buf.as_ptr() as usize,
12008        ))
12009    }
12010    #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
12011    pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
12012        let mut iter = self.clone();
12013        iter.pos = 0;
12014        for attr in iter {
12015            if let OpQstatsGetDumpReply::RxHwDropOverruns(val) = attr? {
12016                return Ok(val);
12017            }
12018        }
12019        Err(ErrorContext::new_missing(
12020            "OpQstatsGetDumpReply",
12021            "RxHwDropOverruns",
12022            self.orig_loc,
12023            self.buf.as_ptr() as usize,
12024        ))
12025    }
12026    #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
12027    pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
12028        let mut iter = self.clone();
12029        iter.pos = 0;
12030        for attr in iter {
12031            if let OpQstatsGetDumpReply::RxCsumComplete(val) = attr? {
12032                return Ok(val);
12033            }
12034        }
12035        Err(ErrorContext::new_missing(
12036            "OpQstatsGetDumpReply",
12037            "RxCsumComplete",
12038            self.orig_loc,
12039            self.buf.as_ptr() as usize,
12040        ))
12041    }
12042    #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
12043    pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
12044        let mut iter = self.clone();
12045        iter.pos = 0;
12046        for attr in iter {
12047            if let OpQstatsGetDumpReply::RxCsumUnnecessary(val) = attr? {
12048                return Ok(val);
12049            }
12050        }
12051        Err(ErrorContext::new_missing(
12052            "OpQstatsGetDumpReply",
12053            "RxCsumUnnecessary",
12054            self.orig_loc,
12055            self.buf.as_ptr() as usize,
12056        ))
12057    }
12058    #[doc = "Number of packets that were not checksummed by device."]
12059    pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
12060        let mut iter = self.clone();
12061        iter.pos = 0;
12062        for attr in iter {
12063            if let OpQstatsGetDumpReply::RxCsumNone(val) = attr? {
12064                return Ok(val);
12065            }
12066        }
12067        Err(ErrorContext::new_missing(
12068            "OpQstatsGetDumpReply",
12069            "RxCsumNone",
12070            self.orig_loc,
12071            self.buf.as_ptr() as usize,
12072        ))
12073    }
12074    #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
12075    pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
12076        let mut iter = self.clone();
12077        iter.pos = 0;
12078        for attr in iter {
12079            if let OpQstatsGetDumpReply::RxCsumBad(val) = attr? {
12080                return Ok(val);
12081            }
12082        }
12083        Err(ErrorContext::new_missing(
12084            "OpQstatsGetDumpReply",
12085            "RxCsumBad",
12086            self.orig_loc,
12087            self.buf.as_ptr() as usize,
12088        ))
12089    }
12090    #[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"]
12091    pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
12092        let mut iter = self.clone();
12093        iter.pos = 0;
12094        for attr in iter {
12095            if let OpQstatsGetDumpReply::RxHwGroPackets(val) = attr? {
12096                return Ok(val);
12097            }
12098        }
12099        Err(ErrorContext::new_missing(
12100            "OpQstatsGetDumpReply",
12101            "RxHwGroPackets",
12102            self.orig_loc,
12103            self.buf.as_ptr() as usize,
12104        ))
12105    }
12106    #[doc = "See `rx-hw-gro-packets`."]
12107    pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
12108        let mut iter = self.clone();
12109        iter.pos = 0;
12110        for attr in iter {
12111            if let OpQstatsGetDumpReply::RxHwGroBytes(val) = attr? {
12112                return Ok(val);
12113            }
12114        }
12115        Err(ErrorContext::new_missing(
12116            "OpQstatsGetDumpReply",
12117            "RxHwGroBytes",
12118            self.orig_loc,
12119            self.buf.as_ptr() as usize,
12120        ))
12121    }
12122    #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
12123    pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
12124        let mut iter = self.clone();
12125        iter.pos = 0;
12126        for attr in iter {
12127            if let OpQstatsGetDumpReply::RxHwGroWirePackets(val) = attr? {
12128                return Ok(val);
12129            }
12130        }
12131        Err(ErrorContext::new_missing(
12132            "OpQstatsGetDumpReply",
12133            "RxHwGroWirePackets",
12134            self.orig_loc,
12135            self.buf.as_ptr() as usize,
12136        ))
12137    }
12138    #[doc = "See `rx-hw-gro-wire-packets`."]
12139    pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
12140        let mut iter = self.clone();
12141        iter.pos = 0;
12142        for attr in iter {
12143            if let OpQstatsGetDumpReply::RxHwGroWireBytes(val) = attr? {
12144                return Ok(val);
12145            }
12146        }
12147        Err(ErrorContext::new_missing(
12148            "OpQstatsGetDumpReply",
12149            "RxHwGroWireBytes",
12150            self.orig_loc,
12151            self.buf.as_ptr() as usize,
12152        ))
12153    }
12154    #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
12155    pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12156        let mut iter = self.clone();
12157        iter.pos = 0;
12158        for attr in iter {
12159            if let OpQstatsGetDumpReply::RxHwDropRatelimits(val) = attr? {
12160                return Ok(val);
12161            }
12162        }
12163        Err(ErrorContext::new_missing(
12164            "OpQstatsGetDumpReply",
12165            "RxHwDropRatelimits",
12166            self.orig_loc,
12167            self.buf.as_ptr() as usize,
12168        ))
12169    }
12170    #[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"]
12171    pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
12172        let mut iter = self.clone();
12173        iter.pos = 0;
12174        for attr in iter {
12175            if let OpQstatsGetDumpReply::TxHwDrops(val) = attr? {
12176                return Ok(val);
12177            }
12178        }
12179        Err(ErrorContext::new_missing(
12180            "OpQstatsGetDumpReply",
12181            "TxHwDrops",
12182            self.orig_loc,
12183            self.buf.as_ptr() as usize,
12184        ))
12185    }
12186    #[doc = "Number of packets dropped because they were invalid or malformed."]
12187    pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
12188        let mut iter = self.clone();
12189        iter.pos = 0;
12190        for attr in iter {
12191            if let OpQstatsGetDumpReply::TxHwDropErrors(val) = attr? {
12192                return Ok(val);
12193            }
12194        }
12195        Err(ErrorContext::new_missing(
12196            "OpQstatsGetDumpReply",
12197            "TxHwDropErrors",
12198            self.orig_loc,
12199            self.buf.as_ptr() as usize,
12200        ))
12201    }
12202    #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
12203    pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
12204        let mut iter = self.clone();
12205        iter.pos = 0;
12206        for attr in iter {
12207            if let OpQstatsGetDumpReply::TxCsumNone(val) = attr? {
12208                return Ok(val);
12209            }
12210        }
12211        Err(ErrorContext::new_missing(
12212            "OpQstatsGetDumpReply",
12213            "TxCsumNone",
12214            self.orig_loc,
12215            self.buf.as_ptr() as usize,
12216        ))
12217    }
12218    #[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"]
12219    pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
12220        let mut iter = self.clone();
12221        iter.pos = 0;
12222        for attr in iter {
12223            if let OpQstatsGetDumpReply::TxNeedsCsum(val) = attr? {
12224                return Ok(val);
12225            }
12226        }
12227        Err(ErrorContext::new_missing(
12228            "OpQstatsGetDumpReply",
12229            "TxNeedsCsum",
12230            self.orig_loc,
12231            self.buf.as_ptr() as usize,
12232        ))
12233    }
12234    #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
12235    pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
12236        let mut iter = self.clone();
12237        iter.pos = 0;
12238        for attr in iter {
12239            if let OpQstatsGetDumpReply::TxHwGsoPackets(val) = attr? {
12240                return Ok(val);
12241            }
12242        }
12243        Err(ErrorContext::new_missing(
12244            "OpQstatsGetDumpReply",
12245            "TxHwGsoPackets",
12246            self.orig_loc,
12247            self.buf.as_ptr() as usize,
12248        ))
12249    }
12250    #[doc = "See `tx-hw-gso-packets`."]
12251    pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
12252        let mut iter = self.clone();
12253        iter.pos = 0;
12254        for attr in iter {
12255            if let OpQstatsGetDumpReply::TxHwGsoBytes(val) = attr? {
12256                return Ok(val);
12257            }
12258        }
12259        Err(ErrorContext::new_missing(
12260            "OpQstatsGetDumpReply",
12261            "TxHwGsoBytes",
12262            self.orig_loc,
12263            self.buf.as_ptr() as usize,
12264        ))
12265    }
12266    #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
12267    pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
12268        let mut iter = self.clone();
12269        iter.pos = 0;
12270        for attr in iter {
12271            if let OpQstatsGetDumpReply::TxHwGsoWirePackets(val) = attr? {
12272                return Ok(val);
12273            }
12274        }
12275        Err(ErrorContext::new_missing(
12276            "OpQstatsGetDumpReply",
12277            "TxHwGsoWirePackets",
12278            self.orig_loc,
12279            self.buf.as_ptr() as usize,
12280        ))
12281    }
12282    #[doc = "See `tx-hw-gso-wire-packets`."]
12283    pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
12284        let mut iter = self.clone();
12285        iter.pos = 0;
12286        for attr in iter {
12287            if let OpQstatsGetDumpReply::TxHwGsoWireBytes(val) = attr? {
12288                return Ok(val);
12289            }
12290        }
12291        Err(ErrorContext::new_missing(
12292            "OpQstatsGetDumpReply",
12293            "TxHwGsoWireBytes",
12294            self.orig_loc,
12295            self.buf.as_ptr() as usize,
12296        ))
12297    }
12298    #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
12299    pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12300        let mut iter = self.clone();
12301        iter.pos = 0;
12302        for attr in iter {
12303            if let OpQstatsGetDumpReply::TxHwDropRatelimits(val) = attr? {
12304                return Ok(val);
12305            }
12306        }
12307        Err(ErrorContext::new_missing(
12308            "OpQstatsGetDumpReply",
12309            "TxHwDropRatelimits",
12310            self.orig_loc,
12311            self.buf.as_ptr() as usize,
12312        ))
12313    }
12314    #[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"]
12315    pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
12316        let mut iter = self.clone();
12317        iter.pos = 0;
12318        for attr in iter {
12319            if let OpQstatsGetDumpReply::TxStop(val) = attr? {
12320                return Ok(val);
12321            }
12322        }
12323        Err(ErrorContext::new_missing(
12324            "OpQstatsGetDumpReply",
12325            "TxStop",
12326            self.orig_loc,
12327            self.buf.as_ptr() as usize,
12328        ))
12329    }
12330    #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
12331    pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
12332        let mut iter = self.clone();
12333        iter.pos = 0;
12334        for attr in iter {
12335            if let OpQstatsGetDumpReply::TxWake(val) = attr? {
12336                return Ok(val);
12337            }
12338        }
12339        Err(ErrorContext::new_missing(
12340            "OpQstatsGetDumpReply",
12341            "TxWake",
12342            self.orig_loc,
12343            self.buf.as_ptr() as usize,
12344        ))
12345    }
12346}
12347impl OpQstatsGetDumpReply {
12348    pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpReply<'a> {
12349        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12350        IterableOpQstatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
12351    }
12352    fn attr_from_type(r#type: u16) -> Option<&'static str> {
12353        Qstats::attr_from_type(r#type)
12354    }
12355}
12356#[derive(Clone, Copy, Default)]
12357pub struct IterableOpQstatsGetDumpReply<'a> {
12358    buf: &'a [u8],
12359    pos: usize,
12360    orig_loc: usize,
12361}
12362impl<'a> IterableOpQstatsGetDumpReply<'a> {
12363    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
12364        Self {
12365            buf,
12366            pos: 0,
12367            orig_loc,
12368        }
12369    }
12370    pub fn get_buf(&self) -> &'a [u8] {
12371        self.buf
12372    }
12373}
12374impl<'a> Iterator for IterableOpQstatsGetDumpReply<'a> {
12375    type Item = Result<OpQstatsGetDumpReply, ErrorContext>;
12376    fn next(&mut self) -> Option<Self::Item> {
12377        if self.buf.len() == self.pos {
12378            return None;
12379        }
12380        let pos = self.pos;
12381        let mut r#type = None;
12382        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
12383            r#type = Some(header.r#type);
12384            let res = match header.r#type {
12385                1u16 => OpQstatsGetDumpReply::Ifindex({
12386                    let res = parse_u32(next);
12387                    let Some(val) = res else { break };
12388                    val
12389                }),
12390                2u16 => OpQstatsGetDumpReply::QueueType({
12391                    let res = parse_u32(next);
12392                    let Some(val) = res else { break };
12393                    val
12394                }),
12395                3u16 => OpQstatsGetDumpReply::QueueId({
12396                    let res = parse_u32(next);
12397                    let Some(val) = res else { break };
12398                    val
12399                }),
12400                8u16 => OpQstatsGetDumpReply::RxPackets({
12401                    let res = parse_u32(next);
12402                    let Some(val) = res else { break };
12403                    val
12404                }),
12405                9u16 => OpQstatsGetDumpReply::RxBytes({
12406                    let res = parse_u32(next);
12407                    let Some(val) = res else { break };
12408                    val
12409                }),
12410                10u16 => OpQstatsGetDumpReply::TxPackets({
12411                    let res = parse_u32(next);
12412                    let Some(val) = res else { break };
12413                    val
12414                }),
12415                11u16 => OpQstatsGetDumpReply::TxBytes({
12416                    let res = parse_u32(next);
12417                    let Some(val) = res else { break };
12418                    val
12419                }),
12420                12u16 => OpQstatsGetDumpReply::RxAllocFail({
12421                    let res = parse_u32(next);
12422                    let Some(val) = res else { break };
12423                    val
12424                }),
12425                13u16 => OpQstatsGetDumpReply::RxHwDrops({
12426                    let res = parse_u32(next);
12427                    let Some(val) = res else { break };
12428                    val
12429                }),
12430                14u16 => OpQstatsGetDumpReply::RxHwDropOverruns({
12431                    let res = parse_u32(next);
12432                    let Some(val) = res else { break };
12433                    val
12434                }),
12435                15u16 => OpQstatsGetDumpReply::RxCsumComplete({
12436                    let res = parse_u32(next);
12437                    let Some(val) = res else { break };
12438                    val
12439                }),
12440                16u16 => OpQstatsGetDumpReply::RxCsumUnnecessary({
12441                    let res = parse_u32(next);
12442                    let Some(val) = res else { break };
12443                    val
12444                }),
12445                17u16 => OpQstatsGetDumpReply::RxCsumNone({
12446                    let res = parse_u32(next);
12447                    let Some(val) = res else { break };
12448                    val
12449                }),
12450                18u16 => OpQstatsGetDumpReply::RxCsumBad({
12451                    let res = parse_u32(next);
12452                    let Some(val) = res else { break };
12453                    val
12454                }),
12455                19u16 => OpQstatsGetDumpReply::RxHwGroPackets({
12456                    let res = parse_u32(next);
12457                    let Some(val) = res else { break };
12458                    val
12459                }),
12460                20u16 => OpQstatsGetDumpReply::RxHwGroBytes({
12461                    let res = parse_u32(next);
12462                    let Some(val) = res else { break };
12463                    val
12464                }),
12465                21u16 => OpQstatsGetDumpReply::RxHwGroWirePackets({
12466                    let res = parse_u32(next);
12467                    let Some(val) = res else { break };
12468                    val
12469                }),
12470                22u16 => OpQstatsGetDumpReply::RxHwGroWireBytes({
12471                    let res = parse_u32(next);
12472                    let Some(val) = res else { break };
12473                    val
12474                }),
12475                23u16 => OpQstatsGetDumpReply::RxHwDropRatelimits({
12476                    let res = parse_u32(next);
12477                    let Some(val) = res else { break };
12478                    val
12479                }),
12480                24u16 => OpQstatsGetDumpReply::TxHwDrops({
12481                    let res = parse_u32(next);
12482                    let Some(val) = res else { break };
12483                    val
12484                }),
12485                25u16 => OpQstatsGetDumpReply::TxHwDropErrors({
12486                    let res = parse_u32(next);
12487                    let Some(val) = res else { break };
12488                    val
12489                }),
12490                26u16 => OpQstatsGetDumpReply::TxCsumNone({
12491                    let res = parse_u32(next);
12492                    let Some(val) = res else { break };
12493                    val
12494                }),
12495                27u16 => OpQstatsGetDumpReply::TxNeedsCsum({
12496                    let res = parse_u32(next);
12497                    let Some(val) = res else { break };
12498                    val
12499                }),
12500                28u16 => OpQstatsGetDumpReply::TxHwGsoPackets({
12501                    let res = parse_u32(next);
12502                    let Some(val) = res else { break };
12503                    val
12504                }),
12505                29u16 => OpQstatsGetDumpReply::TxHwGsoBytes({
12506                    let res = parse_u32(next);
12507                    let Some(val) = res else { break };
12508                    val
12509                }),
12510                30u16 => OpQstatsGetDumpReply::TxHwGsoWirePackets({
12511                    let res = parse_u32(next);
12512                    let Some(val) = res else { break };
12513                    val
12514                }),
12515                31u16 => OpQstatsGetDumpReply::TxHwGsoWireBytes({
12516                    let res = parse_u32(next);
12517                    let Some(val) = res else { break };
12518                    val
12519                }),
12520                32u16 => OpQstatsGetDumpReply::TxHwDropRatelimits({
12521                    let res = parse_u32(next);
12522                    let Some(val) = res else { break };
12523                    val
12524                }),
12525                33u16 => OpQstatsGetDumpReply::TxStop({
12526                    let res = parse_u32(next);
12527                    let Some(val) = res else { break };
12528                    val
12529                }),
12530                34u16 => OpQstatsGetDumpReply::TxWake({
12531                    let res = parse_u32(next);
12532                    let Some(val) = res else { break };
12533                    val
12534                }),
12535                n => {
12536                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
12537                        break;
12538                    } else {
12539                        continue;
12540                    }
12541                }
12542            };
12543            return Some(Ok(res));
12544        }
12545        Some(Err(ErrorContext::new(
12546            "OpQstatsGetDumpReply",
12547            r#type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12548            self.orig_loc,
12549            self.buf.as_ptr().wrapping_add(pos) as usize,
12550        )))
12551    }
12552}
12553impl std::fmt::Debug for IterableOpQstatsGetDumpReply<'_> {
12554    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12555        let mut fmt = f.debug_struct("OpQstatsGetDumpReply");
12556        for attr in self.clone() {
12557            let attr = match attr {
12558                Ok(a) => a,
12559                Err(err) => {
12560                    fmt.finish()?;
12561                    f.write_str("Err(")?;
12562                    err.fmt(f)?;
12563                    return f.write_str(")");
12564                }
12565            };
12566            match attr {
12567                OpQstatsGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
12568                OpQstatsGetDumpReply::QueueType(val) => {
12569                    fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
12570                }
12571                OpQstatsGetDumpReply::QueueId(val) => fmt.field("QueueId", &val),
12572                OpQstatsGetDumpReply::RxPackets(val) => fmt.field("RxPackets", &val),
12573                OpQstatsGetDumpReply::RxBytes(val) => fmt.field("RxBytes", &val),
12574                OpQstatsGetDumpReply::TxPackets(val) => fmt.field("TxPackets", &val),
12575                OpQstatsGetDumpReply::TxBytes(val) => fmt.field("TxBytes", &val),
12576                OpQstatsGetDumpReply::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
12577                OpQstatsGetDumpReply::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
12578                OpQstatsGetDumpReply::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
12579                OpQstatsGetDumpReply::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
12580                OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12581                    fmt.field("RxCsumUnnecessary", &val)
12582                }
12583                OpQstatsGetDumpReply::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
12584                OpQstatsGetDumpReply::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
12585                OpQstatsGetDumpReply::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
12586                OpQstatsGetDumpReply::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
12587                OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12588                    fmt.field("RxHwGroWirePackets", &val)
12589                }
12590                OpQstatsGetDumpReply::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
12591                OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12592                    fmt.field("RxHwDropRatelimits", &val)
12593                }
12594                OpQstatsGetDumpReply::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
12595                OpQstatsGetDumpReply::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
12596                OpQstatsGetDumpReply::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
12597                OpQstatsGetDumpReply::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
12598                OpQstatsGetDumpReply::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
12599                OpQstatsGetDumpReply::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
12600                OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12601                    fmt.field("TxHwGsoWirePackets", &val)
12602                }
12603                OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
12604                OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12605                    fmt.field("TxHwDropRatelimits", &val)
12606                }
12607                OpQstatsGetDumpReply::TxStop(val) => fmt.field("TxStop", &val),
12608                OpQstatsGetDumpReply::TxWake(val) => fmt.field("TxWake", &val),
12609            };
12610        }
12611        fmt.finish()
12612    }
12613}
12614impl IterableOpQstatsGetDumpReply<'_> {
12615    pub fn lookup_attr(
12616        &self,
12617        offset: usize,
12618        missing_type: Option<u16>,
12619    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12620        let mut stack = Vec::new();
12621        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
12622        if cur == offset + PushBuiltinNfgenmsg::len() {
12623            stack.push(("OpQstatsGetDumpReply", offset));
12624            return (
12625                stack,
12626                missing_type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12627            );
12628        }
12629        if cur > offset || cur + self.buf.len() < offset {
12630            return (stack, None);
12631        }
12632        let mut attrs = self.clone();
12633        let mut last_off = cur + attrs.pos;
12634        while let Some(attr) = attrs.next() {
12635            let Ok(attr) = attr else { break };
12636            match attr {
12637                OpQstatsGetDumpReply::Ifindex(val) => {
12638                    if last_off == offset {
12639                        stack.push(("Ifindex", last_off));
12640                        break;
12641                    }
12642                }
12643                OpQstatsGetDumpReply::QueueType(val) => {
12644                    if last_off == offset {
12645                        stack.push(("QueueType", last_off));
12646                        break;
12647                    }
12648                }
12649                OpQstatsGetDumpReply::QueueId(val) => {
12650                    if last_off == offset {
12651                        stack.push(("QueueId", last_off));
12652                        break;
12653                    }
12654                }
12655                OpQstatsGetDumpReply::RxPackets(val) => {
12656                    if last_off == offset {
12657                        stack.push(("RxPackets", last_off));
12658                        break;
12659                    }
12660                }
12661                OpQstatsGetDumpReply::RxBytes(val) => {
12662                    if last_off == offset {
12663                        stack.push(("RxBytes", last_off));
12664                        break;
12665                    }
12666                }
12667                OpQstatsGetDumpReply::TxPackets(val) => {
12668                    if last_off == offset {
12669                        stack.push(("TxPackets", last_off));
12670                        break;
12671                    }
12672                }
12673                OpQstatsGetDumpReply::TxBytes(val) => {
12674                    if last_off == offset {
12675                        stack.push(("TxBytes", last_off));
12676                        break;
12677                    }
12678                }
12679                OpQstatsGetDumpReply::RxAllocFail(val) => {
12680                    if last_off == offset {
12681                        stack.push(("RxAllocFail", last_off));
12682                        break;
12683                    }
12684                }
12685                OpQstatsGetDumpReply::RxHwDrops(val) => {
12686                    if last_off == offset {
12687                        stack.push(("RxHwDrops", last_off));
12688                        break;
12689                    }
12690                }
12691                OpQstatsGetDumpReply::RxHwDropOverruns(val) => {
12692                    if last_off == offset {
12693                        stack.push(("RxHwDropOverruns", last_off));
12694                        break;
12695                    }
12696                }
12697                OpQstatsGetDumpReply::RxCsumComplete(val) => {
12698                    if last_off == offset {
12699                        stack.push(("RxCsumComplete", last_off));
12700                        break;
12701                    }
12702                }
12703                OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12704                    if last_off == offset {
12705                        stack.push(("RxCsumUnnecessary", last_off));
12706                        break;
12707                    }
12708                }
12709                OpQstatsGetDumpReply::RxCsumNone(val) => {
12710                    if last_off == offset {
12711                        stack.push(("RxCsumNone", last_off));
12712                        break;
12713                    }
12714                }
12715                OpQstatsGetDumpReply::RxCsumBad(val) => {
12716                    if last_off == offset {
12717                        stack.push(("RxCsumBad", last_off));
12718                        break;
12719                    }
12720                }
12721                OpQstatsGetDumpReply::RxHwGroPackets(val) => {
12722                    if last_off == offset {
12723                        stack.push(("RxHwGroPackets", last_off));
12724                        break;
12725                    }
12726                }
12727                OpQstatsGetDumpReply::RxHwGroBytes(val) => {
12728                    if last_off == offset {
12729                        stack.push(("RxHwGroBytes", last_off));
12730                        break;
12731                    }
12732                }
12733                OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12734                    if last_off == offset {
12735                        stack.push(("RxHwGroWirePackets", last_off));
12736                        break;
12737                    }
12738                }
12739                OpQstatsGetDumpReply::RxHwGroWireBytes(val) => {
12740                    if last_off == offset {
12741                        stack.push(("RxHwGroWireBytes", last_off));
12742                        break;
12743                    }
12744                }
12745                OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12746                    if last_off == offset {
12747                        stack.push(("RxHwDropRatelimits", last_off));
12748                        break;
12749                    }
12750                }
12751                OpQstatsGetDumpReply::TxHwDrops(val) => {
12752                    if last_off == offset {
12753                        stack.push(("TxHwDrops", last_off));
12754                        break;
12755                    }
12756                }
12757                OpQstatsGetDumpReply::TxHwDropErrors(val) => {
12758                    if last_off == offset {
12759                        stack.push(("TxHwDropErrors", last_off));
12760                        break;
12761                    }
12762                }
12763                OpQstatsGetDumpReply::TxCsumNone(val) => {
12764                    if last_off == offset {
12765                        stack.push(("TxCsumNone", last_off));
12766                        break;
12767                    }
12768                }
12769                OpQstatsGetDumpReply::TxNeedsCsum(val) => {
12770                    if last_off == offset {
12771                        stack.push(("TxNeedsCsum", last_off));
12772                        break;
12773                    }
12774                }
12775                OpQstatsGetDumpReply::TxHwGsoPackets(val) => {
12776                    if last_off == offset {
12777                        stack.push(("TxHwGsoPackets", last_off));
12778                        break;
12779                    }
12780                }
12781                OpQstatsGetDumpReply::TxHwGsoBytes(val) => {
12782                    if last_off == offset {
12783                        stack.push(("TxHwGsoBytes", last_off));
12784                        break;
12785                    }
12786                }
12787                OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12788                    if last_off == offset {
12789                        stack.push(("TxHwGsoWirePackets", last_off));
12790                        break;
12791                    }
12792                }
12793                OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => {
12794                    if last_off == offset {
12795                        stack.push(("TxHwGsoWireBytes", last_off));
12796                        break;
12797                    }
12798                }
12799                OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12800                    if last_off == offset {
12801                        stack.push(("TxHwDropRatelimits", last_off));
12802                        break;
12803                    }
12804                }
12805                OpQstatsGetDumpReply::TxStop(val) => {
12806                    if last_off == offset {
12807                        stack.push(("TxStop", last_off));
12808                        break;
12809                    }
12810                }
12811                OpQstatsGetDumpReply::TxWake(val) => {
12812                    if last_off == offset {
12813                        stack.push(("TxWake", last_off));
12814                        break;
12815                    }
12816                }
12817                _ => {}
12818            };
12819            last_off = cur + attrs.pos;
12820        }
12821        if !stack.is_empty() {
12822            stack.push(("OpQstatsGetDumpReply", cur));
12823        }
12824        (stack, None)
12825    }
12826}
12827#[derive(Debug)]
12828pub struct RequestOpQstatsGetDumpRequest<'r> {
12829    request: Request<'r>,
12830}
12831impl<'r> RequestOpQstatsGetDumpRequest<'r> {
12832    pub fn new(mut request: Request<'r>) -> Self {
12833        PushOpQstatsGetDumpRequest::write_header(&mut request.buf_mut());
12834        Self {
12835            request: request.set_dump(),
12836        }
12837    }
12838    pub fn encode(&mut self) -> PushOpQstatsGetDumpRequest<&mut Vec<u8>> {
12839        PushOpQstatsGetDumpRequest::new_without_header(self.request.buf_mut())
12840    }
12841    pub fn into_encoder(self) -> PushOpQstatsGetDumpRequest<RequestBuf<'r>> {
12842        PushOpQstatsGetDumpRequest::new_without_header(self.request.buf)
12843    }
12844}
12845impl NetlinkRequest for RequestOpQstatsGetDumpRequest<'_> {
12846    type ReplyType<'buf> = IterableOpQstatsGetDumpReply<'buf>;
12847    fn protocol(&self) -> Protocol {
12848        Protocol::Generic("netdev".as_bytes())
12849    }
12850    fn flags(&self) -> u16 {
12851        self.request.flags
12852    }
12853    fn payload(&self) -> &[u8] {
12854        self.request.buf()
12855    }
12856    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
12857        OpQstatsGetDumpReply::new(buf)
12858    }
12859    fn lookup(
12860        buf: &[u8],
12861        offset: usize,
12862        missing_type: Option<u16>,
12863    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12864        OpQstatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
12865    }
12866}
12867#[doc = "Bind dmabuf to netdev"]
12868pub struct PushOpBindRxDoRequest<Prev: Rec> {
12869    pub(crate) prev: Option<Prev>,
12870    pub(crate) header_offset: Option<usize>,
12871}
12872impl<Prev: Rec> Rec for PushOpBindRxDoRequest<Prev> {
12873    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
12874        self.prev.as_mut().unwrap().as_rec_mut()
12875    }
12876}
12877impl<Prev: Rec> PushOpBindRxDoRequest<Prev> {
12878    pub fn new(mut prev: Prev) -> Self {
12879        Self::write_header(&mut prev);
12880        Self::new_without_header(prev)
12881    }
12882    fn new_without_header(prev: Prev) -> Self {
12883        Self {
12884            prev: Some(prev),
12885            header_offset: None,
12886        }
12887    }
12888    fn write_header(prev: &mut Prev) {
12889        let mut header = PushBuiltinNfgenmsg::new();
12890        header.set_cmd(13u8);
12891        header.set_version(1u8);
12892        prev.as_rec_mut().extend(header.as_slice());
12893    }
12894    pub fn end_nested(mut self) -> Prev {
12895        let mut prev = self.prev.take().unwrap();
12896        if let Some(header_offset) = &self.header_offset {
12897            finalize_nested_header(prev.as_rec_mut(), *header_offset);
12898        }
12899        prev
12900    }
12901    #[doc = "netdev ifindex to bind the dmabuf to."]
12902    pub fn push_ifindex(mut self, value: u32) -> Self {
12903        push_header(self.as_rec_mut(), 1u16, 4 as u16);
12904        self.as_rec_mut().extend(value.to_ne_bytes());
12905        self
12906    }
12907    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12908    pub fn nested_queues(mut self) -> PushQueueId<Self> {
12909        let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
12910        PushQueueId {
12911            prev: Some(self),
12912            header_offset: Some(header_offset),
12913        }
12914    }
12915    #[doc = "dmabuf file descriptor to bind."]
12916    pub fn push_fd(mut self, value: u32) -> Self {
12917        push_header(self.as_rec_mut(), 3u16, 4 as u16);
12918        self.as_rec_mut().extend(value.to_ne_bytes());
12919        self
12920    }
12921}
12922impl<Prev: Rec> Drop for PushOpBindRxDoRequest<Prev> {
12923    fn drop(&mut self) {
12924        if let Some(prev) = &mut self.prev {
12925            if let Some(header_offset) = &self.header_offset {
12926                finalize_nested_header(prev.as_rec_mut(), *header_offset);
12927            }
12928        }
12929    }
12930}
12931#[doc = "Bind dmabuf to netdev"]
12932#[derive(Clone)]
12933pub enum OpBindRxDoRequest<'a> {
12934    #[doc = "netdev ifindex to bind the dmabuf to."]
12935    Ifindex(u32),
12936    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12937    Queues(IterableQueueId<'a>),
12938    #[doc = "dmabuf file descriptor to bind."]
12939    Fd(u32),
12940}
12941impl<'a> IterableOpBindRxDoRequest<'a> {
12942    #[doc = "netdev ifindex to bind the dmabuf to."]
12943    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
12944        let mut iter = self.clone();
12945        iter.pos = 0;
12946        for attr in iter {
12947            if let OpBindRxDoRequest::Ifindex(val) = attr? {
12948                return Ok(val);
12949            }
12950        }
12951        Err(ErrorContext::new_missing(
12952            "OpBindRxDoRequest",
12953            "Ifindex",
12954            self.orig_loc,
12955            self.buf.as_ptr() as usize,
12956        ))
12957    }
12958    #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12959    pub fn get_queues(
12960        &self,
12961    ) -> MultiAttrIterable<Self, OpBindRxDoRequest<'a>, IterableQueueId<'a>> {
12962        MultiAttrIterable::new(self.clone(), |variant| {
12963            if let OpBindRxDoRequest::Queues(val) = variant {
12964                Some(val)
12965            } else {
12966                None
12967            }
12968        })
12969    }
12970    #[doc = "dmabuf file descriptor to bind."]
12971    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
12972        let mut iter = self.clone();
12973        iter.pos = 0;
12974        for attr in iter {
12975            if let OpBindRxDoRequest::Fd(val) = attr? {
12976                return Ok(val);
12977            }
12978        }
12979        Err(ErrorContext::new_missing(
12980            "OpBindRxDoRequest",
12981            "Fd",
12982            self.orig_loc,
12983            self.buf.as_ptr() as usize,
12984        ))
12985    }
12986}
12987impl OpBindRxDoRequest<'_> {
12988    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoRequest<'a> {
12989        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12990        IterableOpBindRxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
12991    }
12992    fn attr_from_type(r#type: u16) -> Option<&'static str> {
12993        Dmabuf::attr_from_type(r#type)
12994    }
12995}
12996#[derive(Clone, Copy, Default)]
12997pub struct IterableOpBindRxDoRequest<'a> {
12998    buf: &'a [u8],
12999    pos: usize,
13000    orig_loc: usize,
13001}
13002impl<'a> IterableOpBindRxDoRequest<'a> {
13003    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13004        Self {
13005            buf,
13006            pos: 0,
13007            orig_loc,
13008        }
13009    }
13010    pub fn get_buf(&self) -> &'a [u8] {
13011        self.buf
13012    }
13013}
13014impl<'a> Iterator for IterableOpBindRxDoRequest<'a> {
13015    type Item = Result<OpBindRxDoRequest<'a>, ErrorContext>;
13016    fn next(&mut self) -> Option<Self::Item> {
13017        if self.buf.len() == self.pos {
13018            return None;
13019        }
13020        let pos = self.pos;
13021        let mut r#type = None;
13022        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13023            r#type = Some(header.r#type);
13024            let res = match header.r#type {
13025                1u16 => OpBindRxDoRequest::Ifindex({
13026                    let res = parse_u32(next);
13027                    let Some(val) = res else { break };
13028                    val
13029                }),
13030                2u16 => OpBindRxDoRequest::Queues({
13031                    let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
13032                    let Some(val) = res else { break };
13033                    val
13034                }),
13035                3u16 => OpBindRxDoRequest::Fd({
13036                    let res = parse_u32(next);
13037                    let Some(val) = res else { break };
13038                    val
13039                }),
13040                n => {
13041                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
13042                        break;
13043                    } else {
13044                        continue;
13045                    }
13046                }
13047            };
13048            return Some(Ok(res));
13049        }
13050        Some(Err(ErrorContext::new(
13051            "OpBindRxDoRequest",
13052            r#type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13053            self.orig_loc,
13054            self.buf.as_ptr().wrapping_add(pos) as usize,
13055        )))
13056    }
13057}
13058impl<'a> std::fmt::Debug for IterableOpBindRxDoRequest<'_> {
13059    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13060        let mut fmt = f.debug_struct("OpBindRxDoRequest");
13061        for attr in self.clone() {
13062            let attr = match attr {
13063                Ok(a) => a,
13064                Err(err) => {
13065                    fmt.finish()?;
13066                    f.write_str("Err(")?;
13067                    err.fmt(f)?;
13068                    return f.write_str(")");
13069                }
13070            };
13071            match attr {
13072                OpBindRxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
13073                OpBindRxDoRequest::Queues(val) => fmt.field("Queues", &val),
13074                OpBindRxDoRequest::Fd(val) => fmt.field("Fd", &val),
13075            };
13076        }
13077        fmt.finish()
13078    }
13079}
13080impl IterableOpBindRxDoRequest<'_> {
13081    pub fn lookup_attr(
13082        &self,
13083        offset: usize,
13084        missing_type: Option<u16>,
13085    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13086        let mut stack = Vec::new();
13087        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13088        if cur == offset + PushBuiltinNfgenmsg::len() {
13089            stack.push(("OpBindRxDoRequest", offset));
13090            return (
13091                stack,
13092                missing_type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13093            );
13094        }
13095        if cur > offset || cur + self.buf.len() < offset {
13096            return (stack, None);
13097        }
13098        let mut attrs = self.clone();
13099        let mut last_off = cur + attrs.pos;
13100        let mut missing = None;
13101        while let Some(attr) = attrs.next() {
13102            let Ok(attr) = attr else { break };
13103            match attr {
13104                OpBindRxDoRequest::Ifindex(val) => {
13105                    if last_off == offset {
13106                        stack.push(("Ifindex", last_off));
13107                        break;
13108                    }
13109                }
13110                OpBindRxDoRequest::Queues(val) => {
13111                    (stack, missing) = val.lookup_attr(offset, missing_type);
13112                    if !stack.is_empty() {
13113                        break;
13114                    }
13115                }
13116                OpBindRxDoRequest::Fd(val) => {
13117                    if last_off == offset {
13118                        stack.push(("Fd", last_off));
13119                        break;
13120                    }
13121                }
13122                _ => {}
13123            };
13124            last_off = cur + attrs.pos;
13125        }
13126        if !stack.is_empty() {
13127            stack.push(("OpBindRxDoRequest", cur));
13128        }
13129        (stack, missing)
13130    }
13131}
13132#[doc = "Bind dmabuf to netdev"]
13133pub struct PushOpBindRxDoReply<Prev: Rec> {
13134    pub(crate) prev: Option<Prev>,
13135    pub(crate) header_offset: Option<usize>,
13136}
13137impl<Prev: Rec> Rec for PushOpBindRxDoReply<Prev> {
13138    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13139        self.prev.as_mut().unwrap().as_rec_mut()
13140    }
13141}
13142impl<Prev: Rec> PushOpBindRxDoReply<Prev> {
13143    pub fn new(mut prev: Prev) -> Self {
13144        Self::write_header(&mut prev);
13145        Self::new_without_header(prev)
13146    }
13147    fn new_without_header(prev: Prev) -> Self {
13148        Self {
13149            prev: Some(prev),
13150            header_offset: None,
13151        }
13152    }
13153    fn write_header(prev: &mut Prev) {
13154        let mut header = PushBuiltinNfgenmsg::new();
13155        header.set_cmd(13u8);
13156        header.set_version(1u8);
13157        prev.as_rec_mut().extend(header.as_slice());
13158    }
13159    pub fn end_nested(mut self) -> Prev {
13160        let mut prev = self.prev.take().unwrap();
13161        if let Some(header_offset) = &self.header_offset {
13162            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13163        }
13164        prev
13165    }
13166    #[doc = "id of the dmabuf binding"]
13167    pub fn push_id(mut self, value: u32) -> Self {
13168        push_header(self.as_rec_mut(), 4u16, 4 as u16);
13169        self.as_rec_mut().extend(value.to_ne_bytes());
13170        self
13171    }
13172}
13173impl<Prev: Rec> Drop for PushOpBindRxDoReply<Prev> {
13174    fn drop(&mut self) {
13175        if let Some(prev) = &mut self.prev {
13176            if let Some(header_offset) = &self.header_offset {
13177                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13178            }
13179        }
13180    }
13181}
13182#[doc = "Bind dmabuf to netdev"]
13183#[derive(Clone)]
13184pub enum OpBindRxDoReply {
13185    #[doc = "id of the dmabuf binding"]
13186    Id(u32),
13187}
13188impl<'a> IterableOpBindRxDoReply<'a> {
13189    #[doc = "id of the dmabuf binding"]
13190    pub fn get_id(&self) -> Result<u32, ErrorContext> {
13191        let mut iter = self.clone();
13192        iter.pos = 0;
13193        for attr in iter {
13194            if let OpBindRxDoReply::Id(val) = attr? {
13195                return Ok(val);
13196            }
13197        }
13198        Err(ErrorContext::new_missing(
13199            "OpBindRxDoReply",
13200            "Id",
13201            self.orig_loc,
13202            self.buf.as_ptr() as usize,
13203        ))
13204    }
13205}
13206impl OpBindRxDoReply {
13207    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoReply<'a> {
13208        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13209        IterableOpBindRxDoReply::with_loc(attrs, buf.as_ptr() as usize)
13210    }
13211    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13212        Dmabuf::attr_from_type(r#type)
13213    }
13214}
13215#[derive(Clone, Copy, Default)]
13216pub struct IterableOpBindRxDoReply<'a> {
13217    buf: &'a [u8],
13218    pos: usize,
13219    orig_loc: usize,
13220}
13221impl<'a> IterableOpBindRxDoReply<'a> {
13222    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13223        Self {
13224            buf,
13225            pos: 0,
13226            orig_loc,
13227        }
13228    }
13229    pub fn get_buf(&self) -> &'a [u8] {
13230        self.buf
13231    }
13232}
13233impl<'a> Iterator for IterableOpBindRxDoReply<'a> {
13234    type Item = Result<OpBindRxDoReply, ErrorContext>;
13235    fn next(&mut self) -> Option<Self::Item> {
13236        if self.buf.len() == self.pos {
13237            return None;
13238        }
13239        let pos = self.pos;
13240        let mut r#type = None;
13241        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13242            r#type = Some(header.r#type);
13243            let res = match header.r#type {
13244                4u16 => OpBindRxDoReply::Id({
13245                    let res = parse_u32(next);
13246                    let Some(val) = res else { break };
13247                    val
13248                }),
13249                n => {
13250                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
13251                        break;
13252                    } else {
13253                        continue;
13254                    }
13255                }
13256            };
13257            return Some(Ok(res));
13258        }
13259        Some(Err(ErrorContext::new(
13260            "OpBindRxDoReply",
13261            r#type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13262            self.orig_loc,
13263            self.buf.as_ptr().wrapping_add(pos) as usize,
13264        )))
13265    }
13266}
13267impl std::fmt::Debug for IterableOpBindRxDoReply<'_> {
13268    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13269        let mut fmt = f.debug_struct("OpBindRxDoReply");
13270        for attr in self.clone() {
13271            let attr = match attr {
13272                Ok(a) => a,
13273                Err(err) => {
13274                    fmt.finish()?;
13275                    f.write_str("Err(")?;
13276                    err.fmt(f)?;
13277                    return f.write_str(")");
13278                }
13279            };
13280            match attr {
13281                OpBindRxDoReply::Id(val) => fmt.field("Id", &val),
13282            };
13283        }
13284        fmt.finish()
13285    }
13286}
13287impl IterableOpBindRxDoReply<'_> {
13288    pub fn lookup_attr(
13289        &self,
13290        offset: usize,
13291        missing_type: Option<u16>,
13292    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13293        let mut stack = Vec::new();
13294        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13295        if cur == offset + PushBuiltinNfgenmsg::len() {
13296            stack.push(("OpBindRxDoReply", offset));
13297            return (
13298                stack,
13299                missing_type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13300            );
13301        }
13302        if cur > offset || cur + self.buf.len() < offset {
13303            return (stack, None);
13304        }
13305        let mut attrs = self.clone();
13306        let mut last_off = cur + attrs.pos;
13307        while let Some(attr) = attrs.next() {
13308            let Ok(attr) = attr else { break };
13309            match attr {
13310                OpBindRxDoReply::Id(val) => {
13311                    if last_off == offset {
13312                        stack.push(("Id", last_off));
13313                        break;
13314                    }
13315                }
13316                _ => {}
13317            };
13318            last_off = cur + attrs.pos;
13319        }
13320        if !stack.is_empty() {
13321            stack.push(("OpBindRxDoReply", cur));
13322        }
13323        (stack, None)
13324    }
13325}
13326#[derive(Debug)]
13327pub struct RequestOpBindRxDoRequest<'r> {
13328    request: Request<'r>,
13329}
13330impl<'r> RequestOpBindRxDoRequest<'r> {
13331    pub fn new(mut request: Request<'r>) -> Self {
13332        PushOpBindRxDoRequest::write_header(&mut request.buf_mut());
13333        Self { request: request }
13334    }
13335    pub fn encode(&mut self) -> PushOpBindRxDoRequest<&mut Vec<u8>> {
13336        PushOpBindRxDoRequest::new_without_header(self.request.buf_mut())
13337    }
13338    pub fn into_encoder(self) -> PushOpBindRxDoRequest<RequestBuf<'r>> {
13339        PushOpBindRxDoRequest::new_without_header(self.request.buf)
13340    }
13341}
13342impl NetlinkRequest for RequestOpBindRxDoRequest<'_> {
13343    type ReplyType<'buf> = IterableOpBindRxDoReply<'buf>;
13344    fn protocol(&self) -> Protocol {
13345        Protocol::Generic("netdev".as_bytes())
13346    }
13347    fn flags(&self) -> u16 {
13348        self.request.flags
13349    }
13350    fn payload(&self) -> &[u8] {
13351        self.request.buf()
13352    }
13353    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13354        OpBindRxDoReply::new(buf)
13355    }
13356    fn lookup(
13357        buf: &[u8],
13358        offset: usize,
13359        missing_type: Option<u16>,
13360    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13361        OpBindRxDoRequest::new(buf).lookup_attr(offset, missing_type)
13362    }
13363}
13364#[doc = "Set configurable NAPI instance settings."]
13365pub struct PushOpNapiSetDoRequest<Prev: Rec> {
13366    pub(crate) prev: Option<Prev>,
13367    pub(crate) header_offset: Option<usize>,
13368}
13369impl<Prev: Rec> Rec for PushOpNapiSetDoRequest<Prev> {
13370    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13371        self.prev.as_mut().unwrap().as_rec_mut()
13372    }
13373}
13374impl<Prev: Rec> PushOpNapiSetDoRequest<Prev> {
13375    pub fn new(mut prev: Prev) -> Self {
13376        Self::write_header(&mut prev);
13377        Self::new_without_header(prev)
13378    }
13379    fn new_without_header(prev: Prev) -> Self {
13380        Self {
13381            prev: Some(prev),
13382            header_offset: None,
13383        }
13384    }
13385    fn write_header(prev: &mut Prev) {
13386        let mut header = PushBuiltinNfgenmsg::new();
13387        header.set_cmd(14u8);
13388        header.set_version(1u8);
13389        prev.as_rec_mut().extend(header.as_slice());
13390    }
13391    pub fn end_nested(mut self) -> Prev {
13392        let mut prev = self.prev.take().unwrap();
13393        if let Some(header_offset) = &self.header_offset {
13394            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13395        }
13396        prev
13397    }
13398    #[doc = "ID of the NAPI instance."]
13399    pub fn push_id(mut self, value: u32) -> Self {
13400        push_header(self.as_rec_mut(), 2u16, 4 as u16);
13401        self.as_rec_mut().extend(value.to_ne_bytes());
13402        self
13403    }
13404    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13405    pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
13406        push_header(self.as_rec_mut(), 5u16, 4 as u16);
13407        self.as_rec_mut().extend(value.to_ne_bytes());
13408        self
13409    }
13410    #[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."]
13411    pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
13412        push_header(self.as_rec_mut(), 6u16, 4 as u16);
13413        self.as_rec_mut().extend(value.to_ne_bytes());
13414        self
13415    }
13416    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13417    pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
13418        push_header(self.as_rec_mut(), 7u16, 4 as u16);
13419        self.as_rec_mut().extend(value.to_ne_bytes());
13420        self
13421    }
13422    #[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)"]
13423    pub fn push_threaded(mut self, value: u32) -> Self {
13424        push_header(self.as_rec_mut(), 8u16, 4 as u16);
13425        self.as_rec_mut().extend(value.to_ne_bytes());
13426        self
13427    }
13428}
13429impl<Prev: Rec> Drop for PushOpNapiSetDoRequest<Prev> {
13430    fn drop(&mut self) {
13431        if let Some(prev) = &mut self.prev {
13432            if let Some(header_offset) = &self.header_offset {
13433                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13434            }
13435        }
13436    }
13437}
13438#[doc = "Set configurable NAPI instance settings."]
13439#[derive(Clone)]
13440pub enum OpNapiSetDoRequest {
13441    #[doc = "ID of the NAPI instance."]
13442    Id(u32),
13443    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13444    DeferHardIrqs(u32),
13445    #[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."]
13446    GroFlushTimeout(u32),
13447    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13448    IrqSuspendTimeout(u32),
13449    #[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)"]
13450    Threaded(u32),
13451}
13452impl<'a> IterableOpNapiSetDoRequest<'a> {
13453    #[doc = "ID of the NAPI instance."]
13454    pub fn get_id(&self) -> Result<u32, ErrorContext> {
13455        let mut iter = self.clone();
13456        iter.pos = 0;
13457        for attr in iter {
13458            if let OpNapiSetDoRequest::Id(val) = attr? {
13459                return Ok(val);
13460            }
13461        }
13462        Err(ErrorContext::new_missing(
13463            "OpNapiSetDoRequest",
13464            "Id",
13465            self.orig_loc,
13466            self.buf.as_ptr() as usize,
13467        ))
13468    }
13469    #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13470    pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
13471        let mut iter = self.clone();
13472        iter.pos = 0;
13473        for attr in iter {
13474            if let OpNapiSetDoRequest::DeferHardIrqs(val) = attr? {
13475                return Ok(val);
13476            }
13477        }
13478        Err(ErrorContext::new_missing(
13479            "OpNapiSetDoRequest",
13480            "DeferHardIrqs",
13481            self.orig_loc,
13482            self.buf.as_ptr() as usize,
13483        ))
13484    }
13485    #[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."]
13486    pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
13487        let mut iter = self.clone();
13488        iter.pos = 0;
13489        for attr in iter {
13490            if let OpNapiSetDoRequest::GroFlushTimeout(val) = attr? {
13491                return Ok(val);
13492            }
13493        }
13494        Err(ErrorContext::new_missing(
13495            "OpNapiSetDoRequest",
13496            "GroFlushTimeout",
13497            self.orig_loc,
13498            self.buf.as_ptr() as usize,
13499        ))
13500    }
13501    #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13502    pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
13503        let mut iter = self.clone();
13504        iter.pos = 0;
13505        for attr in iter {
13506            if let OpNapiSetDoRequest::IrqSuspendTimeout(val) = attr? {
13507                return Ok(val);
13508            }
13509        }
13510        Err(ErrorContext::new_missing(
13511            "OpNapiSetDoRequest",
13512            "IrqSuspendTimeout",
13513            self.orig_loc,
13514            self.buf.as_ptr() as usize,
13515        ))
13516    }
13517    #[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)"]
13518    pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
13519        let mut iter = self.clone();
13520        iter.pos = 0;
13521        for attr in iter {
13522            if let OpNapiSetDoRequest::Threaded(val) = attr? {
13523                return Ok(val);
13524            }
13525        }
13526        Err(ErrorContext::new_missing(
13527            "OpNapiSetDoRequest",
13528            "Threaded",
13529            self.orig_loc,
13530            self.buf.as_ptr() as usize,
13531        ))
13532    }
13533}
13534impl OpNapiSetDoRequest {
13535    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoRequest<'a> {
13536        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13537        IterableOpNapiSetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13538    }
13539    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13540        Napi::attr_from_type(r#type)
13541    }
13542}
13543#[derive(Clone, Copy, Default)]
13544pub struct IterableOpNapiSetDoRequest<'a> {
13545    buf: &'a [u8],
13546    pos: usize,
13547    orig_loc: usize,
13548}
13549impl<'a> IterableOpNapiSetDoRequest<'a> {
13550    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13551        Self {
13552            buf,
13553            pos: 0,
13554            orig_loc,
13555        }
13556    }
13557    pub fn get_buf(&self) -> &'a [u8] {
13558        self.buf
13559    }
13560}
13561impl<'a> Iterator for IterableOpNapiSetDoRequest<'a> {
13562    type Item = Result<OpNapiSetDoRequest, ErrorContext>;
13563    fn next(&mut self) -> Option<Self::Item> {
13564        if self.buf.len() == self.pos {
13565            return None;
13566        }
13567        let pos = self.pos;
13568        let mut r#type = None;
13569        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13570            r#type = Some(header.r#type);
13571            let res = match header.r#type {
13572                2u16 => OpNapiSetDoRequest::Id({
13573                    let res = parse_u32(next);
13574                    let Some(val) = res else { break };
13575                    val
13576                }),
13577                5u16 => OpNapiSetDoRequest::DeferHardIrqs({
13578                    let res = parse_u32(next);
13579                    let Some(val) = res else { break };
13580                    val
13581                }),
13582                6u16 => OpNapiSetDoRequest::GroFlushTimeout({
13583                    let res = parse_u32(next);
13584                    let Some(val) = res else { break };
13585                    val
13586                }),
13587                7u16 => OpNapiSetDoRequest::IrqSuspendTimeout({
13588                    let res = parse_u32(next);
13589                    let Some(val) = res else { break };
13590                    val
13591                }),
13592                8u16 => OpNapiSetDoRequest::Threaded({
13593                    let res = parse_u32(next);
13594                    let Some(val) = res else { break };
13595                    val
13596                }),
13597                n => {
13598                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
13599                        break;
13600                    } else {
13601                        continue;
13602                    }
13603                }
13604            };
13605            return Some(Ok(res));
13606        }
13607        Some(Err(ErrorContext::new(
13608            "OpNapiSetDoRequest",
13609            r#type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13610            self.orig_loc,
13611            self.buf.as_ptr().wrapping_add(pos) as usize,
13612        )))
13613    }
13614}
13615impl std::fmt::Debug for IterableOpNapiSetDoRequest<'_> {
13616    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13617        let mut fmt = f.debug_struct("OpNapiSetDoRequest");
13618        for attr in self.clone() {
13619            let attr = match attr {
13620                Ok(a) => a,
13621                Err(err) => {
13622                    fmt.finish()?;
13623                    f.write_str("Err(")?;
13624                    err.fmt(f)?;
13625                    return f.write_str(")");
13626                }
13627            };
13628            match attr {
13629                OpNapiSetDoRequest::Id(val) => fmt.field("Id", &val),
13630                OpNapiSetDoRequest::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
13631                OpNapiSetDoRequest::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
13632                OpNapiSetDoRequest::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
13633                OpNapiSetDoRequest::Threaded(val) => fmt.field(
13634                    "Threaded",
13635                    &FormatEnum(val.into(), NapiThreaded::from_value),
13636                ),
13637            };
13638        }
13639        fmt.finish()
13640    }
13641}
13642impl IterableOpNapiSetDoRequest<'_> {
13643    pub fn lookup_attr(
13644        &self,
13645        offset: usize,
13646        missing_type: Option<u16>,
13647    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13648        let mut stack = Vec::new();
13649        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13650        if cur == offset + PushBuiltinNfgenmsg::len() {
13651            stack.push(("OpNapiSetDoRequest", offset));
13652            return (
13653                stack,
13654                missing_type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13655            );
13656        }
13657        if cur > offset || cur + self.buf.len() < offset {
13658            return (stack, None);
13659        }
13660        let mut attrs = self.clone();
13661        let mut last_off = cur + attrs.pos;
13662        while let Some(attr) = attrs.next() {
13663            let Ok(attr) = attr else { break };
13664            match attr {
13665                OpNapiSetDoRequest::Id(val) => {
13666                    if last_off == offset {
13667                        stack.push(("Id", last_off));
13668                        break;
13669                    }
13670                }
13671                OpNapiSetDoRequest::DeferHardIrqs(val) => {
13672                    if last_off == offset {
13673                        stack.push(("DeferHardIrqs", last_off));
13674                        break;
13675                    }
13676                }
13677                OpNapiSetDoRequest::GroFlushTimeout(val) => {
13678                    if last_off == offset {
13679                        stack.push(("GroFlushTimeout", last_off));
13680                        break;
13681                    }
13682                }
13683                OpNapiSetDoRequest::IrqSuspendTimeout(val) => {
13684                    if last_off == offset {
13685                        stack.push(("IrqSuspendTimeout", last_off));
13686                        break;
13687                    }
13688                }
13689                OpNapiSetDoRequest::Threaded(val) => {
13690                    if last_off == offset {
13691                        stack.push(("Threaded", last_off));
13692                        break;
13693                    }
13694                }
13695                _ => {}
13696            };
13697            last_off = cur + attrs.pos;
13698        }
13699        if !stack.is_empty() {
13700            stack.push(("OpNapiSetDoRequest", cur));
13701        }
13702        (stack, None)
13703    }
13704}
13705#[doc = "Set configurable NAPI instance settings."]
13706pub struct PushOpNapiSetDoReply<Prev: Rec> {
13707    pub(crate) prev: Option<Prev>,
13708    pub(crate) header_offset: Option<usize>,
13709}
13710impl<Prev: Rec> Rec for PushOpNapiSetDoReply<Prev> {
13711    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13712        self.prev.as_mut().unwrap().as_rec_mut()
13713    }
13714}
13715impl<Prev: Rec> PushOpNapiSetDoReply<Prev> {
13716    pub fn new(mut prev: Prev) -> Self {
13717        Self::write_header(&mut prev);
13718        Self::new_without_header(prev)
13719    }
13720    fn new_without_header(prev: Prev) -> Self {
13721        Self {
13722            prev: Some(prev),
13723            header_offset: None,
13724        }
13725    }
13726    fn write_header(prev: &mut Prev) {
13727        let mut header = PushBuiltinNfgenmsg::new();
13728        header.set_cmd(14u8);
13729        header.set_version(1u8);
13730        prev.as_rec_mut().extend(header.as_slice());
13731    }
13732    pub fn end_nested(mut self) -> Prev {
13733        let mut prev = self.prev.take().unwrap();
13734        if let Some(header_offset) = &self.header_offset {
13735            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13736        }
13737        prev
13738    }
13739}
13740impl<Prev: Rec> Drop for PushOpNapiSetDoReply<Prev> {
13741    fn drop(&mut self) {
13742        if let Some(prev) = &mut self.prev {
13743            if let Some(header_offset) = &self.header_offset {
13744                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13745            }
13746        }
13747    }
13748}
13749#[doc = "Set configurable NAPI instance settings."]
13750#[derive(Clone)]
13751pub enum OpNapiSetDoReply {}
13752impl<'a> IterableOpNapiSetDoReply<'a> {}
13753impl OpNapiSetDoReply {
13754    pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoReply<'a> {
13755        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13756        IterableOpNapiSetDoReply::with_loc(attrs, buf.as_ptr() as usize)
13757    }
13758    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13759        Napi::attr_from_type(r#type)
13760    }
13761}
13762#[derive(Clone, Copy, Default)]
13763pub struct IterableOpNapiSetDoReply<'a> {
13764    buf: &'a [u8],
13765    pos: usize,
13766    orig_loc: usize,
13767}
13768impl<'a> IterableOpNapiSetDoReply<'a> {
13769    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13770        Self {
13771            buf,
13772            pos: 0,
13773            orig_loc,
13774        }
13775    }
13776    pub fn get_buf(&self) -> &'a [u8] {
13777        self.buf
13778    }
13779}
13780impl<'a> Iterator for IterableOpNapiSetDoReply<'a> {
13781    type Item = Result<OpNapiSetDoReply, ErrorContext>;
13782    fn next(&mut self) -> Option<Self::Item> {
13783        if self.buf.len() == self.pos {
13784            return None;
13785        }
13786        let pos = self.pos;
13787        let mut r#type = None;
13788        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13789            r#type = Some(header.r#type);
13790            let res = match header.r#type {
13791                n => {
13792                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
13793                        break;
13794                    } else {
13795                        continue;
13796                    }
13797                }
13798            };
13799            return Some(Ok(res));
13800        }
13801        Some(Err(ErrorContext::new(
13802            "OpNapiSetDoReply",
13803            r#type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13804            self.orig_loc,
13805            self.buf.as_ptr().wrapping_add(pos) as usize,
13806        )))
13807    }
13808}
13809impl std::fmt::Debug for IterableOpNapiSetDoReply<'_> {
13810    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13811        let mut fmt = f.debug_struct("OpNapiSetDoReply");
13812        for attr in self.clone() {
13813            let attr = match attr {
13814                Ok(a) => a,
13815                Err(err) => {
13816                    fmt.finish()?;
13817                    f.write_str("Err(")?;
13818                    err.fmt(f)?;
13819                    return f.write_str(")");
13820                }
13821            };
13822            match attr {};
13823        }
13824        fmt.finish()
13825    }
13826}
13827impl IterableOpNapiSetDoReply<'_> {
13828    pub fn lookup_attr(
13829        &self,
13830        offset: usize,
13831        missing_type: Option<u16>,
13832    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13833        let mut stack = Vec::new();
13834        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13835        if cur == offset + PushBuiltinNfgenmsg::len() {
13836            stack.push(("OpNapiSetDoReply", offset));
13837            return (
13838                stack,
13839                missing_type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13840            );
13841        }
13842        (stack, None)
13843    }
13844}
13845#[derive(Debug)]
13846pub struct RequestOpNapiSetDoRequest<'r> {
13847    request: Request<'r>,
13848}
13849impl<'r> RequestOpNapiSetDoRequest<'r> {
13850    pub fn new(mut request: Request<'r>) -> Self {
13851        PushOpNapiSetDoRequest::write_header(&mut request.buf_mut());
13852        Self { request: request }
13853    }
13854    pub fn encode(&mut self) -> PushOpNapiSetDoRequest<&mut Vec<u8>> {
13855        PushOpNapiSetDoRequest::new_without_header(self.request.buf_mut())
13856    }
13857    pub fn into_encoder(self) -> PushOpNapiSetDoRequest<RequestBuf<'r>> {
13858        PushOpNapiSetDoRequest::new_without_header(self.request.buf)
13859    }
13860}
13861impl NetlinkRequest for RequestOpNapiSetDoRequest<'_> {
13862    type ReplyType<'buf> = IterableOpNapiSetDoReply<'buf>;
13863    fn protocol(&self) -> Protocol {
13864        Protocol::Generic("netdev".as_bytes())
13865    }
13866    fn flags(&self) -> u16 {
13867        self.request.flags
13868    }
13869    fn payload(&self) -> &[u8] {
13870        self.request.buf()
13871    }
13872    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13873        OpNapiSetDoReply::new(buf)
13874    }
13875    fn lookup(
13876        buf: &[u8],
13877        offset: usize,
13878        missing_type: Option<u16>,
13879    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13880        OpNapiSetDoRequest::new(buf).lookup_attr(offset, missing_type)
13881    }
13882}
13883#[doc = "Bind dmabuf to netdev for TX"]
13884pub struct PushOpBindTxDoRequest<Prev: Rec> {
13885    pub(crate) prev: Option<Prev>,
13886    pub(crate) header_offset: Option<usize>,
13887}
13888impl<Prev: Rec> Rec for PushOpBindTxDoRequest<Prev> {
13889    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13890        self.prev.as_mut().unwrap().as_rec_mut()
13891    }
13892}
13893impl<Prev: Rec> PushOpBindTxDoRequest<Prev> {
13894    pub fn new(mut prev: Prev) -> Self {
13895        Self::write_header(&mut prev);
13896        Self::new_without_header(prev)
13897    }
13898    fn new_without_header(prev: Prev) -> Self {
13899        Self {
13900            prev: Some(prev),
13901            header_offset: None,
13902        }
13903    }
13904    fn write_header(prev: &mut Prev) {
13905        let mut header = PushBuiltinNfgenmsg::new();
13906        header.set_cmd(15u8);
13907        header.set_version(1u8);
13908        prev.as_rec_mut().extend(header.as_slice());
13909    }
13910    pub fn end_nested(mut self) -> Prev {
13911        let mut prev = self.prev.take().unwrap();
13912        if let Some(header_offset) = &self.header_offset {
13913            finalize_nested_header(prev.as_rec_mut(), *header_offset);
13914        }
13915        prev
13916    }
13917    #[doc = "netdev ifindex to bind the dmabuf to."]
13918    pub fn push_ifindex(mut self, value: u32) -> Self {
13919        push_header(self.as_rec_mut(), 1u16, 4 as u16);
13920        self.as_rec_mut().extend(value.to_ne_bytes());
13921        self
13922    }
13923    #[doc = "dmabuf file descriptor to bind."]
13924    pub fn push_fd(mut self, value: u32) -> Self {
13925        push_header(self.as_rec_mut(), 3u16, 4 as u16);
13926        self.as_rec_mut().extend(value.to_ne_bytes());
13927        self
13928    }
13929}
13930impl<Prev: Rec> Drop for PushOpBindTxDoRequest<Prev> {
13931    fn drop(&mut self) {
13932        if let Some(prev) = &mut self.prev {
13933            if let Some(header_offset) = &self.header_offset {
13934                finalize_nested_header(prev.as_rec_mut(), *header_offset);
13935            }
13936        }
13937    }
13938}
13939#[doc = "Bind dmabuf to netdev for TX"]
13940#[derive(Clone)]
13941pub enum OpBindTxDoRequest {
13942    #[doc = "netdev ifindex to bind the dmabuf to."]
13943    Ifindex(u32),
13944    #[doc = "dmabuf file descriptor to bind."]
13945    Fd(u32),
13946}
13947impl<'a> IterableOpBindTxDoRequest<'a> {
13948    #[doc = "netdev ifindex to bind the dmabuf to."]
13949    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
13950        let mut iter = self.clone();
13951        iter.pos = 0;
13952        for attr in iter {
13953            if let OpBindTxDoRequest::Ifindex(val) = attr? {
13954                return Ok(val);
13955            }
13956        }
13957        Err(ErrorContext::new_missing(
13958            "OpBindTxDoRequest",
13959            "Ifindex",
13960            self.orig_loc,
13961            self.buf.as_ptr() as usize,
13962        ))
13963    }
13964    #[doc = "dmabuf file descriptor to bind."]
13965    pub fn get_fd(&self) -> Result<u32, ErrorContext> {
13966        let mut iter = self.clone();
13967        iter.pos = 0;
13968        for attr in iter {
13969            if let OpBindTxDoRequest::Fd(val) = attr? {
13970                return Ok(val);
13971            }
13972        }
13973        Err(ErrorContext::new_missing(
13974            "OpBindTxDoRequest",
13975            "Fd",
13976            self.orig_loc,
13977            self.buf.as_ptr() as usize,
13978        ))
13979    }
13980}
13981impl OpBindTxDoRequest {
13982    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoRequest<'a> {
13983        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13984        IterableOpBindTxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13985    }
13986    fn attr_from_type(r#type: u16) -> Option<&'static str> {
13987        Dmabuf::attr_from_type(r#type)
13988    }
13989}
13990#[derive(Clone, Copy, Default)]
13991pub struct IterableOpBindTxDoRequest<'a> {
13992    buf: &'a [u8],
13993    pos: usize,
13994    orig_loc: usize,
13995}
13996impl<'a> IterableOpBindTxDoRequest<'a> {
13997    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13998        Self {
13999            buf,
14000            pos: 0,
14001            orig_loc,
14002        }
14003    }
14004    pub fn get_buf(&self) -> &'a [u8] {
14005        self.buf
14006    }
14007}
14008impl<'a> Iterator for IterableOpBindTxDoRequest<'a> {
14009    type Item = Result<OpBindTxDoRequest, ErrorContext>;
14010    fn next(&mut self) -> Option<Self::Item> {
14011        if self.buf.len() == self.pos {
14012            return None;
14013        }
14014        let pos = self.pos;
14015        let mut r#type = None;
14016        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
14017            r#type = Some(header.r#type);
14018            let res = match header.r#type {
14019                1u16 => OpBindTxDoRequest::Ifindex({
14020                    let res = parse_u32(next);
14021                    let Some(val) = res else { break };
14022                    val
14023                }),
14024                3u16 => OpBindTxDoRequest::Fd({
14025                    let res = parse_u32(next);
14026                    let Some(val) = res else { break };
14027                    val
14028                }),
14029                n => {
14030                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
14031                        break;
14032                    } else {
14033                        continue;
14034                    }
14035                }
14036            };
14037            return Some(Ok(res));
14038        }
14039        Some(Err(ErrorContext::new(
14040            "OpBindTxDoRequest",
14041            r#type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14042            self.orig_loc,
14043            self.buf.as_ptr().wrapping_add(pos) as usize,
14044        )))
14045    }
14046}
14047impl std::fmt::Debug for IterableOpBindTxDoRequest<'_> {
14048    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14049        let mut fmt = f.debug_struct("OpBindTxDoRequest");
14050        for attr in self.clone() {
14051            let attr = match attr {
14052                Ok(a) => a,
14053                Err(err) => {
14054                    fmt.finish()?;
14055                    f.write_str("Err(")?;
14056                    err.fmt(f)?;
14057                    return f.write_str(")");
14058                }
14059            };
14060            match attr {
14061                OpBindTxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
14062                OpBindTxDoRequest::Fd(val) => fmt.field("Fd", &val),
14063            };
14064        }
14065        fmt.finish()
14066    }
14067}
14068impl IterableOpBindTxDoRequest<'_> {
14069    pub fn lookup_attr(
14070        &self,
14071        offset: usize,
14072        missing_type: Option<u16>,
14073    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14074        let mut stack = Vec::new();
14075        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14076        if cur == offset + PushBuiltinNfgenmsg::len() {
14077            stack.push(("OpBindTxDoRequest", offset));
14078            return (
14079                stack,
14080                missing_type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14081            );
14082        }
14083        if cur > offset || cur + self.buf.len() < offset {
14084            return (stack, None);
14085        }
14086        let mut attrs = self.clone();
14087        let mut last_off = cur + attrs.pos;
14088        while let Some(attr) = attrs.next() {
14089            let Ok(attr) = attr else { break };
14090            match attr {
14091                OpBindTxDoRequest::Ifindex(val) => {
14092                    if last_off == offset {
14093                        stack.push(("Ifindex", last_off));
14094                        break;
14095                    }
14096                }
14097                OpBindTxDoRequest::Fd(val) => {
14098                    if last_off == offset {
14099                        stack.push(("Fd", last_off));
14100                        break;
14101                    }
14102                }
14103                _ => {}
14104            };
14105            last_off = cur + attrs.pos;
14106        }
14107        if !stack.is_empty() {
14108            stack.push(("OpBindTxDoRequest", cur));
14109        }
14110        (stack, None)
14111    }
14112}
14113#[doc = "Bind dmabuf to netdev for TX"]
14114pub struct PushOpBindTxDoReply<Prev: Rec> {
14115    pub(crate) prev: Option<Prev>,
14116    pub(crate) header_offset: Option<usize>,
14117}
14118impl<Prev: Rec> Rec for PushOpBindTxDoReply<Prev> {
14119    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14120        self.prev.as_mut().unwrap().as_rec_mut()
14121    }
14122}
14123impl<Prev: Rec> PushOpBindTxDoReply<Prev> {
14124    pub fn new(mut prev: Prev) -> Self {
14125        Self::write_header(&mut prev);
14126        Self::new_without_header(prev)
14127    }
14128    fn new_without_header(prev: Prev) -> Self {
14129        Self {
14130            prev: Some(prev),
14131            header_offset: None,
14132        }
14133    }
14134    fn write_header(prev: &mut Prev) {
14135        let mut header = PushBuiltinNfgenmsg::new();
14136        header.set_cmd(15u8);
14137        header.set_version(1u8);
14138        prev.as_rec_mut().extend(header.as_slice());
14139    }
14140    pub fn end_nested(mut self) -> Prev {
14141        let mut prev = self.prev.take().unwrap();
14142        if let Some(header_offset) = &self.header_offset {
14143            finalize_nested_header(prev.as_rec_mut(), *header_offset);
14144        }
14145        prev
14146    }
14147    #[doc = "id of the dmabuf binding"]
14148    pub fn push_id(mut self, value: u32) -> Self {
14149        push_header(self.as_rec_mut(), 4u16, 4 as u16);
14150        self.as_rec_mut().extend(value.to_ne_bytes());
14151        self
14152    }
14153}
14154impl<Prev: Rec> Drop for PushOpBindTxDoReply<Prev> {
14155    fn drop(&mut self) {
14156        if let Some(prev) = &mut self.prev {
14157            if let Some(header_offset) = &self.header_offset {
14158                finalize_nested_header(prev.as_rec_mut(), *header_offset);
14159            }
14160        }
14161    }
14162}
14163#[doc = "Bind dmabuf to netdev for TX"]
14164#[derive(Clone)]
14165pub enum OpBindTxDoReply {
14166    #[doc = "id of the dmabuf binding"]
14167    Id(u32),
14168}
14169impl<'a> IterableOpBindTxDoReply<'a> {
14170    #[doc = "id of the dmabuf binding"]
14171    pub fn get_id(&self) -> Result<u32, ErrorContext> {
14172        let mut iter = self.clone();
14173        iter.pos = 0;
14174        for attr in iter {
14175            if let OpBindTxDoReply::Id(val) = attr? {
14176                return Ok(val);
14177            }
14178        }
14179        Err(ErrorContext::new_missing(
14180            "OpBindTxDoReply",
14181            "Id",
14182            self.orig_loc,
14183            self.buf.as_ptr() as usize,
14184        ))
14185    }
14186}
14187impl OpBindTxDoReply {
14188    pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoReply<'a> {
14189        let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14190        IterableOpBindTxDoReply::with_loc(attrs, buf.as_ptr() as usize)
14191    }
14192    fn attr_from_type(r#type: u16) -> Option<&'static str> {
14193        Dmabuf::attr_from_type(r#type)
14194    }
14195}
14196#[derive(Clone, Copy, Default)]
14197pub struct IterableOpBindTxDoReply<'a> {
14198    buf: &'a [u8],
14199    pos: usize,
14200    orig_loc: usize,
14201}
14202impl<'a> IterableOpBindTxDoReply<'a> {
14203    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14204        Self {
14205            buf,
14206            pos: 0,
14207            orig_loc,
14208        }
14209    }
14210    pub fn get_buf(&self) -> &'a [u8] {
14211        self.buf
14212    }
14213}
14214impl<'a> Iterator for IterableOpBindTxDoReply<'a> {
14215    type Item = Result<OpBindTxDoReply, ErrorContext>;
14216    fn next(&mut self) -> Option<Self::Item> {
14217        if self.buf.len() == self.pos {
14218            return None;
14219        }
14220        let pos = self.pos;
14221        let mut r#type = None;
14222        while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
14223            r#type = Some(header.r#type);
14224            let res = match header.r#type {
14225                4u16 => OpBindTxDoReply::Id({
14226                    let res = parse_u32(next);
14227                    let Some(val) = res else { break };
14228                    val
14229                }),
14230                n => {
14231                    if cfg!(any(test, feature = "deny-unknown-attrs")) {
14232                        break;
14233                    } else {
14234                        continue;
14235                    }
14236                }
14237            };
14238            return Some(Ok(res));
14239        }
14240        Some(Err(ErrorContext::new(
14241            "OpBindTxDoReply",
14242            r#type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14243            self.orig_loc,
14244            self.buf.as_ptr().wrapping_add(pos) as usize,
14245        )))
14246    }
14247}
14248impl std::fmt::Debug for IterableOpBindTxDoReply<'_> {
14249    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14250        let mut fmt = f.debug_struct("OpBindTxDoReply");
14251        for attr in self.clone() {
14252            let attr = match attr {
14253                Ok(a) => a,
14254                Err(err) => {
14255                    fmt.finish()?;
14256                    f.write_str("Err(")?;
14257                    err.fmt(f)?;
14258                    return f.write_str(")");
14259                }
14260            };
14261            match attr {
14262                OpBindTxDoReply::Id(val) => fmt.field("Id", &val),
14263            };
14264        }
14265        fmt.finish()
14266    }
14267}
14268impl IterableOpBindTxDoReply<'_> {
14269    pub fn lookup_attr(
14270        &self,
14271        offset: usize,
14272        missing_type: Option<u16>,
14273    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14274        let mut stack = Vec::new();
14275        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14276        if cur == offset + PushBuiltinNfgenmsg::len() {
14277            stack.push(("OpBindTxDoReply", offset));
14278            return (
14279                stack,
14280                missing_type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14281            );
14282        }
14283        if cur > offset || cur + self.buf.len() < offset {
14284            return (stack, None);
14285        }
14286        let mut attrs = self.clone();
14287        let mut last_off = cur + attrs.pos;
14288        while let Some(attr) = attrs.next() {
14289            let Ok(attr) = attr else { break };
14290            match attr {
14291                OpBindTxDoReply::Id(val) => {
14292                    if last_off == offset {
14293                        stack.push(("Id", last_off));
14294                        break;
14295                    }
14296                }
14297                _ => {}
14298            };
14299            last_off = cur + attrs.pos;
14300        }
14301        if !stack.is_empty() {
14302            stack.push(("OpBindTxDoReply", cur));
14303        }
14304        (stack, None)
14305    }
14306}
14307#[derive(Debug)]
14308pub struct RequestOpBindTxDoRequest<'r> {
14309    request: Request<'r>,
14310}
14311impl<'r> RequestOpBindTxDoRequest<'r> {
14312    pub fn new(mut request: Request<'r>) -> Self {
14313        PushOpBindTxDoRequest::write_header(&mut request.buf_mut());
14314        Self { request: request }
14315    }
14316    pub fn encode(&mut self) -> PushOpBindTxDoRequest<&mut Vec<u8>> {
14317        PushOpBindTxDoRequest::new_without_header(self.request.buf_mut())
14318    }
14319    pub fn into_encoder(self) -> PushOpBindTxDoRequest<RequestBuf<'r>> {
14320        PushOpBindTxDoRequest::new_without_header(self.request.buf)
14321    }
14322}
14323impl NetlinkRequest for RequestOpBindTxDoRequest<'_> {
14324    type ReplyType<'buf> = IterableOpBindTxDoReply<'buf>;
14325    fn protocol(&self) -> Protocol {
14326        Protocol::Generic("netdev".as_bytes())
14327    }
14328    fn flags(&self) -> u16 {
14329        self.request.flags
14330    }
14331    fn payload(&self) -> &[u8] {
14332        self.request.buf()
14333    }
14334    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
14335        OpBindTxDoReply::new(buf)
14336    }
14337    fn lookup(
14338        buf: &[u8],
14339        offset: usize,
14340        missing_type: Option<u16>,
14341    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14342        OpBindTxDoRequest::new(buf).lookup_attr(offset, missing_type)
14343    }
14344}
14345use crate::traits::LookupFn;
14346use crate::utils::RequestBuf;
14347#[derive(Debug)]
14348pub struct Request<'buf> {
14349    buf: RequestBuf<'buf>,
14350    flags: u16,
14351    writeback: Option<&'buf mut Option<RequestInfo>>,
14352}
14353#[allow(unused)]
14354#[derive(Debug, Clone)]
14355pub struct RequestInfo {
14356    protocol: Protocol,
14357    flags: u16,
14358    name: &'static str,
14359    lookup: LookupFn,
14360}
14361impl Request<'static> {
14362    pub fn new() -> Self {
14363        Self::new_from_buf(Vec::new())
14364    }
14365    pub fn new_from_buf(buf: Vec<u8>) -> Self {
14366        Self {
14367            flags: 0,
14368            buf: RequestBuf::Own(buf),
14369            writeback: None,
14370        }
14371    }
14372    pub fn into_buf(self) -> Vec<u8> {
14373        match self.buf {
14374            RequestBuf::Own(buf) => buf,
14375            _ => unreachable!(),
14376        }
14377    }
14378}
14379impl<'buf> Request<'buf> {
14380    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
14381        buf.clear();
14382        Self::new_extend(buf)
14383    }
14384    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
14385        Self {
14386            flags: 0,
14387            buf: RequestBuf::Ref(buf),
14388            writeback: None,
14389        }
14390    }
14391    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
14392        let Some(writeback) = &mut self.writeback else {
14393            return;
14394        };
14395        **writeback = Some(RequestInfo {
14396            protocol,
14397            flags: self.flags,
14398            name,
14399            lookup,
14400        })
14401    }
14402    pub fn buf(&self) -> &Vec<u8> {
14403        self.buf.buf()
14404    }
14405    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
14406        self.buf.buf_mut()
14407    }
14408    #[doc = "Set `NLM_F_CREATE` flag"]
14409    pub fn set_create(mut self) -> Self {
14410        self.flags |= consts::NLM_F_CREATE as u16;
14411        self
14412    }
14413    #[doc = "Set `NLM_F_EXCL` flag"]
14414    pub fn set_excl(mut self) -> Self {
14415        self.flags |= consts::NLM_F_EXCL as u16;
14416        self
14417    }
14418    #[doc = "Set `NLM_F_REPLACE` flag"]
14419    pub fn set_replace(mut self) -> Self {
14420        self.flags |= consts::NLM_F_REPLACE as u16;
14421        self
14422    }
14423    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
14424    pub fn set_change(self) -> Self {
14425        self.set_create().set_replace()
14426    }
14427    #[doc = "Set `NLM_F_APPEND` flag"]
14428    pub fn set_append(mut self) -> Self {
14429        self.flags |= consts::NLM_F_APPEND as u16;
14430        self
14431    }
14432    #[doc = "Set `NLM_F_DUMP` flag"]
14433    fn set_dump(mut self) -> Self {
14434        self.flags |= consts::NLM_F_DUMP as u16;
14435        self
14436    }
14437    pub fn op_dev_get_dump_request(self) -> RequestOpDevGetDumpRequest<'buf> {
14438        let mut res = RequestOpDevGetDumpRequest::new(self);
14439        res.request.do_writeback(
14440            res.protocol(),
14441            "op-dev-get-dump-request",
14442            RequestOpDevGetDumpRequest::lookup,
14443        );
14444        res
14445    }
14446    pub fn op_dev_get_do_request(self) -> RequestOpDevGetDoRequest<'buf> {
14447        let mut res = RequestOpDevGetDoRequest::new(self);
14448        res.request.do_writeback(
14449            res.protocol(),
14450            "op-dev-get-do-request",
14451            RequestOpDevGetDoRequest::lookup,
14452        );
14453        res
14454    }
14455    pub fn op_page_pool_get_dump_request(self) -> RequestOpPagePoolGetDumpRequest<'buf> {
14456        let mut res = RequestOpPagePoolGetDumpRequest::new(self);
14457        res.request.do_writeback(
14458            res.protocol(),
14459            "op-page-pool-get-dump-request",
14460            RequestOpPagePoolGetDumpRequest::lookup,
14461        );
14462        res
14463    }
14464    pub fn op_page_pool_get_do_request(self) -> RequestOpPagePoolGetDoRequest<'buf> {
14465        let mut res = RequestOpPagePoolGetDoRequest::new(self);
14466        res.request.do_writeback(
14467            res.protocol(),
14468            "op-page-pool-get-do-request",
14469            RequestOpPagePoolGetDoRequest::lookup,
14470        );
14471        res
14472    }
14473    pub fn op_page_pool_stats_get_dump_request(self) -> RequestOpPagePoolStatsGetDumpRequest<'buf> {
14474        let mut res = RequestOpPagePoolStatsGetDumpRequest::new(self);
14475        res.request.do_writeback(
14476            res.protocol(),
14477            "op-page-pool-stats-get-dump-request",
14478            RequestOpPagePoolStatsGetDumpRequest::lookup,
14479        );
14480        res
14481    }
14482    pub fn op_page_pool_stats_get_do_request(self) -> RequestOpPagePoolStatsGetDoRequest<'buf> {
14483        let mut res = RequestOpPagePoolStatsGetDoRequest::new(self);
14484        res.request.do_writeback(
14485            res.protocol(),
14486            "op-page-pool-stats-get-do-request",
14487            RequestOpPagePoolStatsGetDoRequest::lookup,
14488        );
14489        res
14490    }
14491    pub fn op_queue_get_dump_request(self) -> RequestOpQueueGetDumpRequest<'buf> {
14492        let mut res = RequestOpQueueGetDumpRequest::new(self);
14493        res.request.do_writeback(
14494            res.protocol(),
14495            "op-queue-get-dump-request",
14496            RequestOpQueueGetDumpRequest::lookup,
14497        );
14498        res
14499    }
14500    pub fn op_queue_get_do_request(self) -> RequestOpQueueGetDoRequest<'buf> {
14501        let mut res = RequestOpQueueGetDoRequest::new(self);
14502        res.request.do_writeback(
14503            res.protocol(),
14504            "op-queue-get-do-request",
14505            RequestOpQueueGetDoRequest::lookup,
14506        );
14507        res
14508    }
14509    pub fn op_napi_get_dump_request(self) -> RequestOpNapiGetDumpRequest<'buf> {
14510        let mut res = RequestOpNapiGetDumpRequest::new(self);
14511        res.request.do_writeback(
14512            res.protocol(),
14513            "op-napi-get-dump-request",
14514            RequestOpNapiGetDumpRequest::lookup,
14515        );
14516        res
14517    }
14518    pub fn op_napi_get_do_request(self) -> RequestOpNapiGetDoRequest<'buf> {
14519        let mut res = RequestOpNapiGetDoRequest::new(self);
14520        res.request.do_writeback(
14521            res.protocol(),
14522            "op-napi-get-do-request",
14523            RequestOpNapiGetDoRequest::lookup,
14524        );
14525        res
14526    }
14527    pub fn op_qstats_get_dump_request(self) -> RequestOpQstatsGetDumpRequest<'buf> {
14528        let mut res = RequestOpQstatsGetDumpRequest::new(self);
14529        res.request.do_writeback(
14530            res.protocol(),
14531            "op-qstats-get-dump-request",
14532            RequestOpQstatsGetDumpRequest::lookup,
14533        );
14534        res
14535    }
14536    pub fn op_bind_rx_do_request(self) -> RequestOpBindRxDoRequest<'buf> {
14537        let mut res = RequestOpBindRxDoRequest::new(self);
14538        res.request.do_writeback(
14539            res.protocol(),
14540            "op-bind-rx-do-request",
14541            RequestOpBindRxDoRequest::lookup,
14542        );
14543        res
14544    }
14545    pub fn op_napi_set_do_request(self) -> RequestOpNapiSetDoRequest<'buf> {
14546        let mut res = RequestOpNapiSetDoRequest::new(self);
14547        res.request.do_writeback(
14548            res.protocol(),
14549            "op-napi-set-do-request",
14550            RequestOpNapiSetDoRequest::lookup,
14551        );
14552        res
14553    }
14554    pub fn op_bind_tx_do_request(self) -> RequestOpBindTxDoRequest<'buf> {
14555        let mut res = RequestOpBindTxDoRequest::new(self);
14556        res.request.do_writeback(
14557            res.protocol(),
14558            "op-bind-tx-do-request",
14559            RequestOpBindTxDoRequest::lookup,
14560        );
14561        res
14562    }
14563}