Skip to main content

netlink_bindings/ovs_vport/
mod.rs

1#![doc = "OVS vport 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::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "ovs_vport";
17pub const PROTONAME_CSTR: &CStr = c"ovs_vport";
18#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
19#[derive(Debug, Clone, Copy)]
20pub enum VportType {
21    Unspec = 0,
22    Netdev = 1,
23    Internal = 2,
24    Gre = 3,
25    Vxlan = 4,
26    Geneve = 5,
27}
28impl VportType {
29    pub fn from_value(value: u64) -> Option<Self> {
30        Some(match value {
31            0 => Self::Unspec,
32            1 => Self::Netdev,
33            2 => Self::Internal,
34            3 => Self::Gre,
35            4 => Self::Vxlan,
36            5 => Self::Geneve,
37            _ => return None,
38        })
39    }
40}
41#[derive(Debug)]
42#[repr(C, packed(4))]
43pub struct OvsHeader {
44    pub dp_ifindex: u32,
45}
46impl Clone for OvsHeader {
47    fn clone(&self) -> Self {
48        Self::new_from_array(*self.as_array())
49    }
50}
51#[doc = "Create zero-initialized struct"]
52impl Default for OvsHeader {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57impl OvsHeader {
58    #[doc = "Create zero-initialized struct"]
59    pub fn new() -> Self {
60        Self::new_from_array([0u8; Self::len()])
61    }
62    #[doc = "Copy from contents from slice"]
63    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
64        if other.len() != Self::len() {
65            return None;
66        }
67        let mut buf = [0u8; Self::len()];
68        buf.clone_from_slice(other);
69        Some(Self::new_from_array(buf))
70    }
71    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
72    pub fn new_from_zeroed(other: &[u8]) -> Self {
73        let mut buf = [0u8; Self::len()];
74        let len = buf.len().min(other.len());
75        buf[..len].clone_from_slice(&other[..len]);
76        Self::new_from_array(buf)
77    }
78    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
79        unsafe { std::mem::transmute(buf) }
80    }
81    pub fn as_slice(&self) -> &[u8] {
82        unsafe {
83            let ptr: *const u8 = std::mem::transmute(self as *const Self);
84            std::slice::from_raw_parts(ptr, Self::len())
85        }
86    }
87    pub fn from_slice(buf: &[u8]) -> &Self {
88        assert!(buf.len() >= Self::len());
89        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
90        unsafe { std::mem::transmute(buf.as_ptr()) }
91    }
92    pub fn as_array(&self) -> &[u8; 4usize] {
93        unsafe { std::mem::transmute(self) }
94    }
95    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
96        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
97        unsafe { std::mem::transmute(buf) }
98    }
99    pub fn into_array(self) -> [u8; 4usize] {
100        unsafe { std::mem::transmute(self) }
101    }
102    pub const fn len() -> usize {
103        const _: () = assert!(std::mem::size_of::<OvsHeader>() == 4usize);
104        4usize
105    }
106}
107#[repr(C, packed(4))]
108pub struct OvsVportStats {
109    pub rx_packets: u64,
110    pub tx_packets: u64,
111    pub rx_bytes: u64,
112    pub tx_bytes: u64,
113    pub rx_errors: u64,
114    pub tx_errors: u64,
115    pub rx_dropped: u64,
116    pub tx_dropped: u64,
117}
118impl Clone for OvsVportStats {
119    fn clone(&self) -> Self {
120        Self::new_from_array(*self.as_array())
121    }
122}
123#[doc = "Create zero-initialized struct"]
124impl Default for OvsVportStats {
125    fn default() -> Self {
126        Self::new()
127    }
128}
129impl OvsVportStats {
130    #[doc = "Create zero-initialized struct"]
131    pub fn new() -> Self {
132        Self::new_from_array([0u8; Self::len()])
133    }
134    #[doc = "Copy from contents from slice"]
135    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
136        if other.len() != Self::len() {
137            return None;
138        }
139        let mut buf = [0u8; Self::len()];
140        buf.clone_from_slice(other);
141        Some(Self::new_from_array(buf))
142    }
143    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
144    pub fn new_from_zeroed(other: &[u8]) -> Self {
145        let mut buf = [0u8; Self::len()];
146        let len = buf.len().min(other.len());
147        buf[..len].clone_from_slice(&other[..len]);
148        Self::new_from_array(buf)
149    }
150    pub fn new_from_array(buf: [u8; 64usize]) -> Self {
151        unsafe { std::mem::transmute(buf) }
152    }
153    pub fn as_slice(&self) -> &[u8] {
154        unsafe {
155            let ptr: *const u8 = std::mem::transmute(self as *const Self);
156            std::slice::from_raw_parts(ptr, Self::len())
157        }
158    }
159    pub fn from_slice(buf: &[u8]) -> &Self {
160        assert!(buf.len() >= Self::len());
161        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
162        unsafe { std::mem::transmute(buf.as_ptr()) }
163    }
164    pub fn as_array(&self) -> &[u8; 64usize] {
165        unsafe { std::mem::transmute(self) }
166    }
167    pub fn from_array(buf: &[u8; 64usize]) -> &Self {
168        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
169        unsafe { std::mem::transmute(buf) }
170    }
171    pub fn into_array(self) -> [u8; 64usize] {
172        unsafe { std::mem::transmute(self) }
173    }
174    pub const fn len() -> usize {
175        const _: () = assert!(std::mem::size_of::<OvsVportStats>() == 64usize);
176        64usize
177    }
178}
179impl std::fmt::Debug for OvsVportStats {
180    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        fmt.debug_struct("OvsVportStats")
182            .field("rx_packets", &{ self.rx_packets })
183            .field("tx_packets", &{ self.tx_packets })
184            .field("rx_bytes", &{ self.rx_bytes })
185            .field("tx_bytes", &{ self.tx_bytes })
186            .field("rx_errors", &{ self.rx_errors })
187            .field("tx_errors", &{ self.tx_errors })
188            .field("rx_dropped", &{ self.rx_dropped })
189            .field("tx_dropped", &{ self.tx_dropped })
190            .finish()
191    }
192}
193#[derive(Clone)]
194pub enum VportOptions {
195    DstPort(u32),
196    Extension(u32),
197}
198impl<'a> IterableVportOptions<'a> {
199    pub fn get_dst_port(&self) -> Result<u32, ErrorContext> {
200        let mut iter = self.clone();
201        iter.pos = 0;
202        for attr in iter {
203            if let VportOptions::DstPort(val) = attr? {
204                return Ok(val);
205            }
206        }
207        Err(ErrorContext::new_missing(
208            "VportOptions",
209            "DstPort",
210            self.orig_loc,
211            self.buf.as_ptr() as usize,
212        ))
213    }
214    pub fn get_extension(&self) -> Result<u32, ErrorContext> {
215        let mut iter = self.clone();
216        iter.pos = 0;
217        for attr in iter {
218            if let VportOptions::Extension(val) = attr? {
219                return Ok(val);
220            }
221        }
222        Err(ErrorContext::new_missing(
223            "VportOptions",
224            "Extension",
225            self.orig_loc,
226            self.buf.as_ptr() as usize,
227        ))
228    }
229}
230impl VportOptions {
231    pub fn new<'a>(buf: &'a [u8]) -> IterableVportOptions<'a> {
232        IterableVportOptions::with_loc(buf, buf.as_ptr() as usize)
233    }
234    fn attr_from_type(r#type: u16) -> Option<&'static str> {
235        let res = match r#type {
236            1u16 => "DstPort",
237            2u16 => "Extension",
238            _ => return None,
239        };
240        Some(res)
241    }
242}
243#[derive(Clone, Copy, Default)]
244pub struct IterableVportOptions<'a> {
245    buf: &'a [u8],
246    pos: usize,
247    orig_loc: usize,
248}
249impl<'a> IterableVportOptions<'a> {
250    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
251        Self {
252            buf,
253            pos: 0,
254            orig_loc,
255        }
256    }
257    pub fn get_buf(&self) -> &'a [u8] {
258        self.buf
259    }
260}
261impl<'a> Iterator for IterableVportOptions<'a> {
262    type Item = Result<VportOptions, ErrorContext>;
263    fn next(&mut self) -> Option<Self::Item> {
264        let pos = self.pos;
265        let mut r#type;
266        loop {
267            r#type = None;
268            if self.buf.len() == self.pos {
269                return None;
270            }
271            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
272                break;
273            };
274            r#type = Some(header.r#type);
275            let res = match header.r#type {
276                1u16 => VportOptions::DstPort({
277                    let res = parse_u32(next);
278                    let Some(val) = res else { break };
279                    val
280                }),
281                2u16 => VportOptions::Extension({
282                    let res = parse_u32(next);
283                    let Some(val) = res else { break };
284                    val
285                }),
286                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
287                n => continue,
288            };
289            return Some(Ok(res));
290        }
291        Some(Err(ErrorContext::new(
292            "VportOptions",
293            r#type.and_then(|t| VportOptions::attr_from_type(t)),
294            self.orig_loc,
295            self.buf.as_ptr().wrapping_add(pos) as usize,
296        )))
297    }
298}
299impl std::fmt::Debug for IterableVportOptions<'_> {
300    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301        let mut fmt = f.debug_struct("VportOptions");
302        for attr in self.clone() {
303            let attr = match attr {
304                Ok(a) => a,
305                Err(err) => {
306                    fmt.finish()?;
307                    f.write_str("Err(")?;
308                    err.fmt(f)?;
309                    return f.write_str(")");
310                }
311            };
312            match attr {
313                VportOptions::DstPort(val) => fmt.field("DstPort", &val),
314                VportOptions::Extension(val) => fmt.field("Extension", &val),
315            };
316        }
317        fmt.finish()
318    }
319}
320impl IterableVportOptions<'_> {
321    pub fn lookup_attr(
322        &self,
323        offset: usize,
324        missing_type: Option<u16>,
325    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
326        let mut stack = Vec::new();
327        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
328        if missing_type.is_some() && cur == offset {
329            stack.push(("VportOptions", offset));
330            return (
331                stack,
332                missing_type.and_then(|t| VportOptions::attr_from_type(t)),
333            );
334        }
335        if cur > offset || cur + self.buf.len() < offset {
336            return (stack, None);
337        }
338        let mut attrs = self.clone();
339        let mut last_off = cur + attrs.pos;
340        while let Some(attr) = attrs.next() {
341            let Ok(attr) = attr else { break };
342            match attr {
343                VportOptions::DstPort(val) => {
344                    if last_off == offset {
345                        stack.push(("DstPort", last_off));
346                        break;
347                    }
348                }
349                VportOptions::Extension(val) => {
350                    if last_off == offset {
351                        stack.push(("Extension", last_off));
352                        break;
353                    }
354                }
355                _ => {}
356            };
357            last_off = cur + attrs.pos;
358        }
359        if !stack.is_empty() {
360            stack.push(("VportOptions", cur));
361        }
362        (stack, None)
363    }
364}
365#[derive(Clone)]
366pub enum UpcallStats {
367    Success(u64),
368    Fail(u64),
369}
370impl<'a> IterableUpcallStats<'a> {
371    pub fn get_success(&self) -> Result<u64, ErrorContext> {
372        let mut iter = self.clone();
373        iter.pos = 0;
374        for attr in iter {
375            if let UpcallStats::Success(val) = attr? {
376                return Ok(val);
377            }
378        }
379        Err(ErrorContext::new_missing(
380            "UpcallStats",
381            "Success",
382            self.orig_loc,
383            self.buf.as_ptr() as usize,
384        ))
385    }
386    pub fn get_fail(&self) -> Result<u64, ErrorContext> {
387        let mut iter = self.clone();
388        iter.pos = 0;
389        for attr in iter {
390            if let UpcallStats::Fail(val) = attr? {
391                return Ok(val);
392            }
393        }
394        Err(ErrorContext::new_missing(
395            "UpcallStats",
396            "Fail",
397            self.orig_loc,
398            self.buf.as_ptr() as usize,
399        ))
400    }
401}
402impl UpcallStats {
403    pub fn new<'a>(buf: &'a [u8]) -> IterableUpcallStats<'a> {
404        IterableUpcallStats::with_loc(buf, buf.as_ptr() as usize)
405    }
406    fn attr_from_type(r#type: u16) -> Option<&'static str> {
407        let res = match r#type {
408            0u16 => "Success",
409            1u16 => "Fail",
410            _ => return None,
411        };
412        Some(res)
413    }
414}
415#[derive(Clone, Copy, Default)]
416pub struct IterableUpcallStats<'a> {
417    buf: &'a [u8],
418    pos: usize,
419    orig_loc: usize,
420}
421impl<'a> IterableUpcallStats<'a> {
422    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
423        Self {
424            buf,
425            pos: 0,
426            orig_loc,
427        }
428    }
429    pub fn get_buf(&self) -> &'a [u8] {
430        self.buf
431    }
432}
433impl<'a> Iterator for IterableUpcallStats<'a> {
434    type Item = Result<UpcallStats, ErrorContext>;
435    fn next(&mut self) -> Option<Self::Item> {
436        let pos = self.pos;
437        let mut r#type;
438        loop {
439            r#type = None;
440            if self.buf.len() == self.pos {
441                return None;
442            }
443            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
444                break;
445            };
446            r#type = Some(header.r#type);
447            let res = match header.r#type {
448                0u16 => UpcallStats::Success({
449                    let res = parse_u64(next);
450                    let Some(val) = res else { break };
451                    val
452                }),
453                1u16 => UpcallStats::Fail({
454                    let res = parse_u64(next);
455                    let Some(val) = res else { break };
456                    val
457                }),
458                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
459                n => continue,
460            };
461            return Some(Ok(res));
462        }
463        Some(Err(ErrorContext::new(
464            "UpcallStats",
465            r#type.and_then(|t| UpcallStats::attr_from_type(t)),
466            self.orig_loc,
467            self.buf.as_ptr().wrapping_add(pos) as usize,
468        )))
469    }
470}
471impl std::fmt::Debug for IterableUpcallStats<'_> {
472    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
473        let mut fmt = f.debug_struct("UpcallStats");
474        for attr in self.clone() {
475            let attr = match attr {
476                Ok(a) => a,
477                Err(err) => {
478                    fmt.finish()?;
479                    f.write_str("Err(")?;
480                    err.fmt(f)?;
481                    return f.write_str(")");
482                }
483            };
484            match attr {
485                UpcallStats::Success(val) => fmt.field("Success", &val),
486                UpcallStats::Fail(val) => fmt.field("Fail", &val),
487            };
488        }
489        fmt.finish()
490    }
491}
492impl IterableUpcallStats<'_> {
493    pub fn lookup_attr(
494        &self,
495        offset: usize,
496        missing_type: Option<u16>,
497    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
498        let mut stack = Vec::new();
499        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
500        if missing_type.is_some() && cur == offset {
501            stack.push(("UpcallStats", offset));
502            return (
503                stack,
504                missing_type.and_then(|t| UpcallStats::attr_from_type(t)),
505            );
506        }
507        if cur > offset || cur + self.buf.len() < offset {
508            return (stack, None);
509        }
510        let mut attrs = self.clone();
511        let mut last_off = cur + attrs.pos;
512        while let Some(attr) = attrs.next() {
513            let Ok(attr) = attr else { break };
514            match attr {
515                UpcallStats::Success(val) => {
516                    if last_off == offset {
517                        stack.push(("Success", last_off));
518                        break;
519                    }
520                }
521                UpcallStats::Fail(val) => {
522                    if last_off == offset {
523                        stack.push(("Fail", last_off));
524                        break;
525                    }
526                }
527                _ => {}
528            };
529            last_off = cur + attrs.pos;
530        }
531        if !stack.is_empty() {
532            stack.push(("UpcallStats", cur));
533        }
534        (stack, None)
535    }
536}
537#[derive(Clone)]
538pub enum Vport<'a> {
539    PortNo(u32),
540    #[doc = "Associated type: [`VportType`] (enum)"]
541    Type(u32),
542    Name(&'a CStr),
543    Options(IterableVportOptions<'a>),
544    UpcallPid(&'a [u8]),
545    Stats(OvsVportStats),
546    Ifindex(u32),
547    Netnsid(u32),
548    UpcallStats(IterableUpcallStats<'a>),
549}
550impl<'a> IterableVport<'a> {
551    pub fn get_port_no(&self) -> Result<u32, ErrorContext> {
552        let mut iter = self.clone();
553        iter.pos = 0;
554        for attr in iter {
555            if let Vport::PortNo(val) = attr? {
556                return Ok(val);
557            }
558        }
559        Err(ErrorContext::new_missing(
560            "Vport",
561            "PortNo",
562            self.orig_loc,
563            self.buf.as_ptr() as usize,
564        ))
565    }
566    #[doc = "Associated type: [`VportType`] (enum)"]
567    pub fn get_type(&self) -> Result<u32, ErrorContext> {
568        let mut iter = self.clone();
569        iter.pos = 0;
570        for attr in iter {
571            if let Vport::Type(val) = attr? {
572                return Ok(val);
573            }
574        }
575        Err(ErrorContext::new_missing(
576            "Vport",
577            "Type",
578            self.orig_loc,
579            self.buf.as_ptr() as usize,
580        ))
581    }
582    pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
583        let mut iter = self.clone();
584        iter.pos = 0;
585        for attr in iter {
586            if let Vport::Name(val) = attr? {
587                return Ok(val);
588            }
589        }
590        Err(ErrorContext::new_missing(
591            "Vport",
592            "Name",
593            self.orig_loc,
594            self.buf.as_ptr() as usize,
595        ))
596    }
597    pub fn get_options(&self) -> Result<IterableVportOptions<'a>, ErrorContext> {
598        let mut iter = self.clone();
599        iter.pos = 0;
600        for attr in iter {
601            if let Vport::Options(val) = attr? {
602                return Ok(val);
603            }
604        }
605        Err(ErrorContext::new_missing(
606            "Vport",
607            "Options",
608            self.orig_loc,
609            self.buf.as_ptr() as usize,
610        ))
611    }
612    pub fn get_upcall_pid(&self) -> Result<&'a [u8], ErrorContext> {
613        let mut iter = self.clone();
614        iter.pos = 0;
615        for attr in iter {
616            if let Vport::UpcallPid(val) = attr? {
617                return Ok(val);
618            }
619        }
620        Err(ErrorContext::new_missing(
621            "Vport",
622            "UpcallPid",
623            self.orig_loc,
624            self.buf.as_ptr() as usize,
625        ))
626    }
627    pub fn get_stats(&self) -> Result<OvsVportStats, ErrorContext> {
628        let mut iter = self.clone();
629        iter.pos = 0;
630        for attr in iter {
631            if let Vport::Stats(val) = attr? {
632                return Ok(val);
633            }
634        }
635        Err(ErrorContext::new_missing(
636            "Vport",
637            "Stats",
638            self.orig_loc,
639            self.buf.as_ptr() as usize,
640        ))
641    }
642    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
643        let mut iter = self.clone();
644        iter.pos = 0;
645        for attr in iter {
646            if let Vport::Ifindex(val) = attr? {
647                return Ok(val);
648            }
649        }
650        Err(ErrorContext::new_missing(
651            "Vport",
652            "Ifindex",
653            self.orig_loc,
654            self.buf.as_ptr() as usize,
655        ))
656    }
657    pub fn get_netnsid(&self) -> Result<u32, ErrorContext> {
658        let mut iter = self.clone();
659        iter.pos = 0;
660        for attr in iter {
661            if let Vport::Netnsid(val) = attr? {
662                return Ok(val);
663            }
664        }
665        Err(ErrorContext::new_missing(
666            "Vport",
667            "Netnsid",
668            self.orig_loc,
669            self.buf.as_ptr() as usize,
670        ))
671    }
672    pub fn get_upcall_stats(&self) -> Result<IterableUpcallStats<'a>, ErrorContext> {
673        let mut iter = self.clone();
674        iter.pos = 0;
675        for attr in iter {
676            if let Vport::UpcallStats(val) = attr? {
677                return Ok(val);
678            }
679        }
680        Err(ErrorContext::new_missing(
681            "Vport",
682            "UpcallStats",
683            self.orig_loc,
684            self.buf.as_ptr() as usize,
685        ))
686    }
687}
688impl Vport<'_> {
689    pub fn new<'a>(buf: &'a [u8]) -> IterableVport<'a> {
690        IterableVport::with_loc(buf, buf.as_ptr() as usize)
691    }
692    fn attr_from_type(r#type: u16) -> Option<&'static str> {
693        let res = match r#type {
694            0u16 => "Unspec",
695            1u16 => "PortNo",
696            2u16 => "Type",
697            3u16 => "Name",
698            4u16 => "Options",
699            5u16 => "UpcallPid",
700            6u16 => "Stats",
701            7u16 => "Pad",
702            8u16 => "Ifindex",
703            9u16 => "Netnsid",
704            10u16 => "UpcallStats",
705            _ => return None,
706        };
707        Some(res)
708    }
709}
710#[derive(Clone, Copy, Default)]
711pub struct IterableVport<'a> {
712    buf: &'a [u8],
713    pos: usize,
714    orig_loc: usize,
715}
716impl<'a> IterableVport<'a> {
717    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
718        Self {
719            buf,
720            pos: 0,
721            orig_loc,
722        }
723    }
724    pub fn get_buf(&self) -> &'a [u8] {
725        self.buf
726    }
727}
728impl<'a> Iterator for IterableVport<'a> {
729    type Item = Result<Vport<'a>, ErrorContext>;
730    fn next(&mut self) -> Option<Self::Item> {
731        let pos = self.pos;
732        let mut r#type;
733        loop {
734            r#type = None;
735            if self.buf.len() == self.pos {
736                return None;
737            }
738            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
739                break;
740            };
741            r#type = Some(header.r#type);
742            let res = match header.r#type {
743                1u16 => Vport::PortNo({
744                    let res = parse_u32(next);
745                    let Some(val) = res else { break };
746                    val
747                }),
748                2u16 => Vport::Type({
749                    let res = parse_u32(next);
750                    let Some(val) = res else { break };
751                    val
752                }),
753                3u16 => Vport::Name({
754                    let res = CStr::from_bytes_with_nul(next).ok();
755                    let Some(val) = res else { break };
756                    val
757                }),
758                4u16 => Vport::Options({
759                    let res = Some(IterableVportOptions::with_loc(next, self.orig_loc));
760                    let Some(val) = res else { break };
761                    val
762                }),
763                5u16 => Vport::UpcallPid({
764                    let res = Some(next);
765                    let Some(val) = res else { break };
766                    val
767                }),
768                6u16 => Vport::Stats({
769                    let res = Some(OvsVportStats::new_from_zeroed(next));
770                    let Some(val) = res else { break };
771                    val
772                }),
773                8u16 => Vport::Ifindex({
774                    let res = parse_u32(next);
775                    let Some(val) = res else { break };
776                    val
777                }),
778                9u16 => Vport::Netnsid({
779                    let res = parse_u32(next);
780                    let Some(val) = res else { break };
781                    val
782                }),
783                10u16 => Vport::UpcallStats({
784                    let res = Some(IterableUpcallStats::with_loc(next, self.orig_loc));
785                    let Some(val) = res else { break };
786                    val
787                }),
788                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
789                n => continue,
790            };
791            return Some(Ok(res));
792        }
793        Some(Err(ErrorContext::new(
794            "Vport",
795            r#type.and_then(|t| Vport::attr_from_type(t)),
796            self.orig_loc,
797            self.buf.as_ptr().wrapping_add(pos) as usize,
798        )))
799    }
800}
801impl<'a> std::fmt::Debug for IterableVport<'_> {
802    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
803        let mut fmt = f.debug_struct("Vport");
804        for attr in self.clone() {
805            let attr = match attr {
806                Ok(a) => a,
807                Err(err) => {
808                    fmt.finish()?;
809                    f.write_str("Err(")?;
810                    err.fmt(f)?;
811                    return f.write_str(")");
812                }
813            };
814            match attr {
815                Vport::PortNo(val) => fmt.field("PortNo", &val),
816                Vport::Type(val) => {
817                    fmt.field("Type", &FormatEnum(val.into(), VportType::from_value))
818                }
819                Vport::Name(val) => fmt.field("Name", &val),
820                Vport::Options(val) => fmt.field("Options", &val),
821                Vport::UpcallPid(val) => fmt.field("UpcallPid", &val),
822                Vport::Stats(val) => fmt.field("Stats", &val),
823                Vport::Ifindex(val) => fmt.field("Ifindex", &val),
824                Vport::Netnsid(val) => fmt.field("Netnsid", &val),
825                Vport::UpcallStats(val) => fmt.field("UpcallStats", &val),
826            };
827        }
828        fmt.finish()
829    }
830}
831impl IterableVport<'_> {
832    pub fn lookup_attr(
833        &self,
834        offset: usize,
835        missing_type: Option<u16>,
836    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
837        let mut stack = Vec::new();
838        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
839        if missing_type.is_some() && cur == offset {
840            stack.push(("Vport", offset));
841            return (stack, missing_type.and_then(|t| Vport::attr_from_type(t)));
842        }
843        if cur > offset || cur + self.buf.len() < offset {
844            return (stack, None);
845        }
846        let mut attrs = self.clone();
847        let mut last_off = cur + attrs.pos;
848        let mut missing = None;
849        while let Some(attr) = attrs.next() {
850            let Ok(attr) = attr else { break };
851            match attr {
852                Vport::PortNo(val) => {
853                    if last_off == offset {
854                        stack.push(("PortNo", last_off));
855                        break;
856                    }
857                }
858                Vport::Type(val) => {
859                    if last_off == offset {
860                        stack.push(("Type", last_off));
861                        break;
862                    }
863                }
864                Vport::Name(val) => {
865                    if last_off == offset {
866                        stack.push(("Name", last_off));
867                        break;
868                    }
869                }
870                Vport::Options(val) => {
871                    (stack, missing) = val.lookup_attr(offset, missing_type);
872                    if !stack.is_empty() {
873                        break;
874                    }
875                }
876                Vport::UpcallPid(val) => {
877                    if last_off == offset {
878                        stack.push(("UpcallPid", last_off));
879                        break;
880                    }
881                }
882                Vport::Stats(val) => {
883                    if last_off == offset {
884                        stack.push(("Stats", last_off));
885                        break;
886                    }
887                }
888                Vport::Ifindex(val) => {
889                    if last_off == offset {
890                        stack.push(("Ifindex", last_off));
891                        break;
892                    }
893                }
894                Vport::Netnsid(val) => {
895                    if last_off == offset {
896                        stack.push(("Netnsid", last_off));
897                        break;
898                    }
899                }
900                Vport::UpcallStats(val) => {
901                    (stack, missing) = val.lookup_attr(offset, missing_type);
902                    if !stack.is_empty() {
903                        break;
904                    }
905                }
906                _ => {}
907            };
908            last_off = cur + attrs.pos;
909        }
910        if !stack.is_empty() {
911            stack.push(("Vport", cur));
912        }
913        (stack, missing)
914    }
915}
916pub struct PushVportOptions<Prev: Rec> {
917    pub(crate) prev: Option<Prev>,
918    pub(crate) header_offset: Option<usize>,
919}
920impl<Prev: Rec> Rec for PushVportOptions<Prev> {
921    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
922        self.prev.as_mut().unwrap().as_rec_mut()
923    }
924    fn as_rec(&self) -> &Vec<u8> {
925        self.prev.as_ref().unwrap().as_rec()
926    }
927}
928impl<Prev: Rec> PushVportOptions<Prev> {
929    pub fn new(prev: Prev) -> Self {
930        Self {
931            prev: Some(prev),
932            header_offset: None,
933        }
934    }
935    pub fn end_nested(mut self) -> Prev {
936        let mut prev = self.prev.take().unwrap();
937        if let Some(header_offset) = &self.header_offset {
938            finalize_nested_header(prev.as_rec_mut(), *header_offset);
939        }
940        prev
941    }
942    pub fn push_dst_port(mut self, value: u32) -> Self {
943        push_header(self.as_rec_mut(), 1u16, 4 as u16);
944        self.as_rec_mut().extend(value.to_ne_bytes());
945        self
946    }
947    pub fn push_extension(mut self, value: u32) -> Self {
948        push_header(self.as_rec_mut(), 2u16, 4 as u16);
949        self.as_rec_mut().extend(value.to_ne_bytes());
950        self
951    }
952}
953impl<Prev: Rec> Drop for PushVportOptions<Prev> {
954    fn drop(&mut self) {
955        if let Some(prev) = &mut self.prev {
956            if let Some(header_offset) = &self.header_offset {
957                finalize_nested_header(prev.as_rec_mut(), *header_offset);
958            }
959        }
960    }
961}
962pub struct PushUpcallStats<Prev: Rec> {
963    pub(crate) prev: Option<Prev>,
964    pub(crate) header_offset: Option<usize>,
965}
966impl<Prev: Rec> Rec for PushUpcallStats<Prev> {
967    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
968        self.prev.as_mut().unwrap().as_rec_mut()
969    }
970    fn as_rec(&self) -> &Vec<u8> {
971        self.prev.as_ref().unwrap().as_rec()
972    }
973}
974impl<Prev: Rec> PushUpcallStats<Prev> {
975    pub fn new(prev: Prev) -> Self {
976        Self {
977            prev: Some(prev),
978            header_offset: None,
979        }
980    }
981    pub fn end_nested(mut self) -> Prev {
982        let mut prev = self.prev.take().unwrap();
983        if let Some(header_offset) = &self.header_offset {
984            finalize_nested_header(prev.as_rec_mut(), *header_offset);
985        }
986        prev
987    }
988    pub fn push_success(mut self, value: u64) -> Self {
989        push_header(self.as_rec_mut(), 0u16, 8 as u16);
990        self.as_rec_mut().extend(value.to_ne_bytes());
991        self
992    }
993    pub fn push_fail(mut self, value: u64) -> Self {
994        push_header(self.as_rec_mut(), 1u16, 8 as u16);
995        self.as_rec_mut().extend(value.to_ne_bytes());
996        self
997    }
998}
999impl<Prev: Rec> Drop for PushUpcallStats<Prev> {
1000    fn drop(&mut self) {
1001        if let Some(prev) = &mut self.prev {
1002            if let Some(header_offset) = &self.header_offset {
1003                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1004            }
1005        }
1006    }
1007}
1008pub struct PushVport<Prev: Rec> {
1009    pub(crate) prev: Option<Prev>,
1010    pub(crate) header_offset: Option<usize>,
1011}
1012impl<Prev: Rec> Rec for PushVport<Prev> {
1013    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1014        self.prev.as_mut().unwrap().as_rec_mut()
1015    }
1016    fn as_rec(&self) -> &Vec<u8> {
1017        self.prev.as_ref().unwrap().as_rec()
1018    }
1019}
1020impl<Prev: Rec> PushVport<Prev> {
1021    pub fn new(prev: Prev) -> Self {
1022        Self {
1023            prev: Some(prev),
1024            header_offset: None,
1025        }
1026    }
1027    pub fn end_nested(mut self) -> Prev {
1028        let mut prev = self.prev.take().unwrap();
1029        if let Some(header_offset) = &self.header_offset {
1030            finalize_nested_header(prev.as_rec_mut(), *header_offset);
1031        }
1032        prev
1033    }
1034    pub fn push_port_no(mut self, value: u32) -> Self {
1035        push_header(self.as_rec_mut(), 1u16, 4 as u16);
1036        self.as_rec_mut().extend(value.to_ne_bytes());
1037        self
1038    }
1039    #[doc = "Associated type: [`VportType`] (enum)"]
1040    pub fn push_type(mut self, value: u32) -> Self {
1041        push_header(self.as_rec_mut(), 2u16, 4 as u16);
1042        self.as_rec_mut().extend(value.to_ne_bytes());
1043        self
1044    }
1045    pub fn push_name(mut self, value: &CStr) -> Self {
1046        push_header(
1047            self.as_rec_mut(),
1048            3u16,
1049            value.to_bytes_with_nul().len() as u16,
1050        );
1051        self.as_rec_mut().extend(value.to_bytes_with_nul());
1052        self
1053    }
1054    pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
1055        push_header(self.as_rec_mut(), 3u16, (value.len() + 1) as u16);
1056        self.as_rec_mut().extend(value);
1057        self.as_rec_mut().push(0);
1058        self
1059    }
1060    pub fn nested_options(mut self) -> PushVportOptions<Self> {
1061        let header_offset = push_nested_header(self.as_rec_mut(), 4u16);
1062        PushVportOptions {
1063            prev: Some(self),
1064            header_offset: Some(header_offset),
1065        }
1066    }
1067    pub fn push_upcall_pid(mut self, value: &[u8]) -> Self {
1068        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
1069        self.as_rec_mut().extend(value);
1070        self
1071    }
1072    pub fn push_stats(mut self, value: OvsVportStats) -> Self {
1073        push_header(self.as_rec_mut(), 6u16, value.as_slice().len() as u16);
1074        self.as_rec_mut().extend(value.as_slice());
1075        self
1076    }
1077    pub fn push_ifindex(mut self, value: u32) -> Self {
1078        push_header(self.as_rec_mut(), 8u16, 4 as u16);
1079        self.as_rec_mut().extend(value.to_ne_bytes());
1080        self
1081    }
1082    pub fn push_netnsid(mut self, value: u32) -> Self {
1083        push_header(self.as_rec_mut(), 9u16, 4 as u16);
1084        self.as_rec_mut().extend(value.to_ne_bytes());
1085        self
1086    }
1087    pub fn nested_upcall_stats(mut self) -> PushUpcallStats<Self> {
1088        let header_offset = push_nested_header(self.as_rec_mut(), 10u16);
1089        PushUpcallStats {
1090            prev: Some(self),
1091            header_offset: Some(header_offset),
1092        }
1093    }
1094}
1095impl<Prev: Rec> Drop for PushVport<Prev> {
1096    fn drop(&mut self) {
1097        if let Some(prev) = &mut self.prev {
1098            if let Some(header_offset) = &self.header_offset {
1099                finalize_nested_header(prev.as_rec_mut(), *header_offset);
1100            }
1101        }
1102    }
1103}
1104pub struct NotifGroup;
1105impl NotifGroup {
1106    pub const OVS_VPORT: &str = "ovs_vport";
1107    pub const OVS_VPORT_CSTR: &CStr = c"ovs_vport";
1108}
1109#[doc = "Create a new OVS vport\nRequest attributes:\n- [.push_type()](PushVport::push_type)\n- [.push_name()](PushVport::push_name)\n- [.nested_options()](PushVport::nested_options)\n- [.push_upcall_pid()](PushVport::push_upcall_pid)\n- [.push_ifindex()](PushVport::push_ifindex)\n"]
1110#[derive(Debug)]
1111pub struct OpNewDo<'r> {
1112    request: Request<'r>,
1113}
1114impl<'r> OpNewDo<'r> {
1115    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
1116        Self::write_header(request.buf_mut(), header);
1117        Self { request: request }
1118    }
1119    pub fn encode_request<'buf>(
1120        buf: &'buf mut Vec<u8>,
1121        header: &OvsHeader,
1122    ) -> PushVport<&'buf mut Vec<u8>> {
1123        Self::write_header(buf, header);
1124        PushVport::new(buf)
1125    }
1126    pub fn encode(&mut self) -> PushVport<&mut Vec<u8>> {
1127        PushVport::new(self.request.buf_mut())
1128    }
1129    pub fn into_encoder(self) -> PushVport<RequestBuf<'r>> {
1130        PushVport::new(self.request.buf)
1131    }
1132    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableVport<'a>) {
1133        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
1134        (
1135            OvsHeader::new_from_slice(header).unwrap_or_default(),
1136            IterableVport::with_loc(attrs, buf.as_ptr() as usize),
1137        )
1138    }
1139    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
1140        prev.as_rec_mut().extend(header.as_slice());
1141    }
1142}
1143impl NetlinkRequest for OpNewDo<'_> {
1144    fn protocol(&self) -> Protocol {
1145        Protocol::Generic("ovs_vport".as_bytes())
1146    }
1147    fn flags(&self) -> u16 {
1148        self.request.flags
1149    }
1150    fn payload(&self) -> &[u8] {
1151        self.request.buf()
1152    }
1153    type ReplyType<'buf> = (OvsHeader, IterableVport<'buf>);
1154    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1155        Self::decode_request(buf)
1156    }
1157    fn lookup(
1158        buf: &[u8],
1159        offset: usize,
1160        missing_type: Option<u16>,
1161    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1162        Self::decode_request(buf)
1163            .1
1164            .lookup_attr(offset, missing_type)
1165    }
1166}
1167#[doc = "Delete existing OVS vport from a data path\nRequest attributes:\n- [.push_port_no()](PushVport::push_port_no)\n- [.push_type()](PushVport::push_type)\n- [.push_name()](PushVport::push_name)\n"]
1168#[derive(Debug)]
1169pub struct OpDelDo<'r> {
1170    request: Request<'r>,
1171}
1172impl<'r> OpDelDo<'r> {
1173    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
1174        Self::write_header(request.buf_mut(), header);
1175        Self { request: request }
1176    }
1177    pub fn encode_request<'buf>(
1178        buf: &'buf mut Vec<u8>,
1179        header: &OvsHeader,
1180    ) -> PushVport<&'buf mut Vec<u8>> {
1181        Self::write_header(buf, header);
1182        PushVport::new(buf)
1183    }
1184    pub fn encode(&mut self) -> PushVport<&mut Vec<u8>> {
1185        PushVport::new(self.request.buf_mut())
1186    }
1187    pub fn into_encoder(self) -> PushVport<RequestBuf<'r>> {
1188        PushVport::new(self.request.buf)
1189    }
1190    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableVport<'a>) {
1191        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
1192        (
1193            OvsHeader::new_from_slice(header).unwrap_or_default(),
1194            IterableVport::with_loc(attrs, buf.as_ptr() as usize),
1195        )
1196    }
1197    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
1198        prev.as_rec_mut().extend(header.as_slice());
1199    }
1200}
1201impl NetlinkRequest for OpDelDo<'_> {
1202    fn protocol(&self) -> Protocol {
1203        Protocol::Generic("ovs_vport".as_bytes())
1204    }
1205    fn flags(&self) -> u16 {
1206        self.request.flags
1207    }
1208    fn payload(&self) -> &[u8] {
1209        self.request.buf()
1210    }
1211    type ReplyType<'buf> = (OvsHeader, IterableVport<'buf>);
1212    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1213        Self::decode_request(buf)
1214    }
1215    fn lookup(
1216        buf: &[u8],
1217        offset: usize,
1218        missing_type: Option<u16>,
1219    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1220        Self::decode_request(buf)
1221            .1
1222            .lookup_attr(offset, missing_type)
1223    }
1224}
1225#[doc = "Get / dump OVS vport configuration and state\nRequest attributes:\n- [.push_name()](PushVport::push_name)\n\nReply attributes:\n- [.get_port_no()](IterableVport::get_port_no)\n- [.get_type()](IterableVport::get_type)\n- [.get_name()](IterableVport::get_name)\n- [.get_upcall_pid()](IterableVport::get_upcall_pid)\n- [.get_stats()](IterableVport::get_stats)\n- [.get_ifindex()](IterableVport::get_ifindex)\n- [.get_netnsid()](IterableVport::get_netnsid)\n- [.get_upcall_stats()](IterableVport::get_upcall_stats)\n"]
1226#[derive(Debug)]
1227pub struct OpGetDump<'r> {
1228    request: Request<'r>,
1229}
1230impl<'r> OpGetDump<'r> {
1231    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
1232        Self::write_header(request.buf_mut(), header);
1233        Self {
1234            request: request.set_dump(),
1235        }
1236    }
1237    pub fn encode_request<'buf>(
1238        buf: &'buf mut Vec<u8>,
1239        header: &OvsHeader,
1240    ) -> PushVport<&'buf mut Vec<u8>> {
1241        Self::write_header(buf, header);
1242        PushVport::new(buf)
1243    }
1244    pub fn encode(&mut self) -> PushVport<&mut Vec<u8>> {
1245        PushVport::new(self.request.buf_mut())
1246    }
1247    pub fn into_encoder(self) -> PushVport<RequestBuf<'r>> {
1248        PushVport::new(self.request.buf)
1249    }
1250    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableVport<'a>) {
1251        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
1252        (
1253            OvsHeader::new_from_slice(header).unwrap_or_default(),
1254            IterableVport::with_loc(attrs, buf.as_ptr() as usize),
1255        )
1256    }
1257    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
1258        prev.as_rec_mut().extend(header.as_slice());
1259    }
1260}
1261impl NetlinkRequest for OpGetDump<'_> {
1262    fn protocol(&self) -> Protocol {
1263        Protocol::Generic("ovs_vport".as_bytes())
1264    }
1265    fn flags(&self) -> u16 {
1266        self.request.flags
1267    }
1268    fn payload(&self) -> &[u8] {
1269        self.request.buf()
1270    }
1271    type ReplyType<'buf> = (OvsHeader, IterableVport<'buf>);
1272    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1273        Self::decode_request(buf)
1274    }
1275    fn lookup(
1276        buf: &[u8],
1277        offset: usize,
1278        missing_type: Option<u16>,
1279    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1280        Self::decode_request(buf)
1281            .1
1282            .lookup_attr(offset, missing_type)
1283    }
1284}
1285#[doc = "Get / dump OVS vport configuration and state\nRequest attributes:\n- [.push_name()](PushVport::push_name)\n\nReply attributes:\n- [.get_port_no()](IterableVport::get_port_no)\n- [.get_type()](IterableVport::get_type)\n- [.get_name()](IterableVport::get_name)\n- [.get_upcall_pid()](IterableVport::get_upcall_pid)\n- [.get_stats()](IterableVport::get_stats)\n- [.get_ifindex()](IterableVport::get_ifindex)\n- [.get_netnsid()](IterableVport::get_netnsid)\n- [.get_upcall_stats()](IterableVport::get_upcall_stats)\n"]
1286#[derive(Debug)]
1287pub struct OpGetDo<'r> {
1288    request: Request<'r>,
1289}
1290impl<'r> OpGetDo<'r> {
1291    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
1292        Self::write_header(request.buf_mut(), header);
1293        Self { request: request }
1294    }
1295    pub fn encode_request<'buf>(
1296        buf: &'buf mut Vec<u8>,
1297        header: &OvsHeader,
1298    ) -> PushVport<&'buf mut Vec<u8>> {
1299        Self::write_header(buf, header);
1300        PushVport::new(buf)
1301    }
1302    pub fn encode(&mut self) -> PushVport<&mut Vec<u8>> {
1303        PushVport::new(self.request.buf_mut())
1304    }
1305    pub fn into_encoder(self) -> PushVport<RequestBuf<'r>> {
1306        PushVport::new(self.request.buf)
1307    }
1308    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableVport<'a>) {
1309        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
1310        (
1311            OvsHeader::new_from_slice(header).unwrap_or_default(),
1312            IterableVport::with_loc(attrs, buf.as_ptr() as usize),
1313        )
1314    }
1315    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
1316        prev.as_rec_mut().extend(header.as_slice());
1317    }
1318}
1319impl NetlinkRequest for OpGetDo<'_> {
1320    fn protocol(&self) -> Protocol {
1321        Protocol::Generic("ovs_vport".as_bytes())
1322    }
1323    fn flags(&self) -> u16 {
1324        self.request.flags
1325    }
1326    fn payload(&self) -> &[u8] {
1327        self.request.buf()
1328    }
1329    type ReplyType<'buf> = (OvsHeader, IterableVport<'buf>);
1330    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1331        Self::decode_request(buf)
1332    }
1333    fn lookup(
1334        buf: &[u8],
1335        offset: usize,
1336        missing_type: Option<u16>,
1337    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1338        Self::decode_request(buf)
1339            .1
1340            .lookup_attr(offset, missing_type)
1341    }
1342}
1343use crate::traits::LookupFn;
1344use crate::utils::RequestBuf;
1345#[derive(Debug)]
1346pub struct Request<'buf> {
1347    buf: RequestBuf<'buf>,
1348    flags: u16,
1349    writeback: Option<&'buf mut Option<RequestInfo>>,
1350}
1351#[allow(unused)]
1352#[derive(Debug, Clone)]
1353pub struct RequestInfo {
1354    protocol: Protocol,
1355    flags: u16,
1356    name: &'static str,
1357    lookup: LookupFn,
1358}
1359impl Request<'static> {
1360    pub fn new() -> Self {
1361        Self::new_from_buf(Vec::new())
1362    }
1363    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1364        Self {
1365            flags: 0,
1366            buf: RequestBuf::Own(buf),
1367            writeback: None,
1368        }
1369    }
1370    pub fn into_buf(self) -> Vec<u8> {
1371        match self.buf {
1372            RequestBuf::Own(buf) => buf,
1373            _ => unreachable!(),
1374        }
1375    }
1376}
1377impl<'buf> Request<'buf> {
1378    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1379        buf.clear();
1380        Self::new_extend(buf)
1381    }
1382    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1383        Self {
1384            flags: 0,
1385            buf: RequestBuf::Ref(buf),
1386            writeback: None,
1387        }
1388    }
1389    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1390        let Some(writeback) = &mut self.writeback else {
1391            return;
1392        };
1393        **writeback = Some(RequestInfo {
1394            protocol,
1395            flags: self.flags,
1396            name,
1397            lookup,
1398        })
1399    }
1400    pub fn buf(&self) -> &Vec<u8> {
1401        self.buf.buf()
1402    }
1403    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1404        self.buf.buf_mut()
1405    }
1406    #[doc = "Set `NLM_F_CREATE` flag"]
1407    pub fn set_create(mut self) -> Self {
1408        self.flags |= consts::NLM_F_CREATE as u16;
1409        self
1410    }
1411    #[doc = "Set `NLM_F_EXCL` flag"]
1412    pub fn set_excl(mut self) -> Self {
1413        self.flags |= consts::NLM_F_EXCL as u16;
1414        self
1415    }
1416    #[doc = "Set `NLM_F_REPLACE` flag"]
1417    pub fn set_replace(mut self) -> Self {
1418        self.flags |= consts::NLM_F_REPLACE as u16;
1419        self
1420    }
1421    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1422    pub fn set_change(self) -> Self {
1423        self.set_create().set_replace()
1424    }
1425    #[doc = "Set `NLM_F_APPEND` flag"]
1426    pub fn set_append(mut self) -> Self {
1427        self.flags |= consts::NLM_F_APPEND as u16;
1428        self
1429    }
1430    #[doc = "Set `self.flags |= flags`"]
1431    pub fn set_flags(mut self, flags: u16) -> Self {
1432        self.flags |= flags;
1433        self
1434    }
1435    #[doc = "Set `self.flags ^= self.flags & flags`"]
1436    pub fn unset_flags(mut self, flags: u16) -> Self {
1437        self.flags ^= self.flags & flags;
1438        self
1439    }
1440    #[doc = "Set `NLM_F_DUMP` flag"]
1441    fn set_dump(mut self) -> Self {
1442        self.flags |= consts::NLM_F_DUMP as u16;
1443        self
1444    }
1445    #[doc = "Create a new OVS vport\nRequest attributes:\n- [.push_type()](PushVport::push_type)\n- [.push_name()](PushVport::push_name)\n- [.nested_options()](PushVport::nested_options)\n- [.push_upcall_pid()](PushVport::push_upcall_pid)\n- [.push_ifindex()](PushVport::push_ifindex)\n"]
1446    pub fn op_new_do(self, header: &OvsHeader) -> OpNewDo<'buf> {
1447        let mut res = OpNewDo::new(self, header);
1448        res.request
1449            .do_writeback(res.protocol(), "op-new-do", OpNewDo::lookup);
1450        res
1451    }
1452    #[doc = "Delete existing OVS vport from a data path\nRequest attributes:\n- [.push_port_no()](PushVport::push_port_no)\n- [.push_type()](PushVport::push_type)\n- [.push_name()](PushVport::push_name)\n"]
1453    pub fn op_del_do(self, header: &OvsHeader) -> OpDelDo<'buf> {
1454        let mut res = OpDelDo::new(self, header);
1455        res.request
1456            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
1457        res
1458    }
1459    #[doc = "Get / dump OVS vport configuration and state\nRequest attributes:\n- [.push_name()](PushVport::push_name)\n\nReply attributes:\n- [.get_port_no()](IterableVport::get_port_no)\n- [.get_type()](IterableVport::get_type)\n- [.get_name()](IterableVport::get_name)\n- [.get_upcall_pid()](IterableVport::get_upcall_pid)\n- [.get_stats()](IterableVport::get_stats)\n- [.get_ifindex()](IterableVport::get_ifindex)\n- [.get_netnsid()](IterableVport::get_netnsid)\n- [.get_upcall_stats()](IterableVport::get_upcall_stats)\n"]
1460    pub fn op_get_dump(self, header: &OvsHeader) -> OpGetDump<'buf> {
1461        let mut res = OpGetDump::new(self, header);
1462        res.request
1463            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
1464        res
1465    }
1466    #[doc = "Get / dump OVS vport configuration and state\nRequest attributes:\n- [.push_name()](PushVport::push_name)\n\nReply attributes:\n- [.get_port_no()](IterableVport::get_port_no)\n- [.get_type()](IterableVport::get_type)\n- [.get_name()](IterableVport::get_name)\n- [.get_upcall_pid()](IterableVport::get_upcall_pid)\n- [.get_stats()](IterableVport::get_stats)\n- [.get_ifindex()](IterableVport::get_ifindex)\n- [.get_netnsid()](IterableVport::get_netnsid)\n- [.get_upcall_stats()](IterableVport::get_upcall_stats)\n"]
1467    pub fn op_get_do(self, header: &OvsHeader) -> OpGetDo<'buf> {
1468        let mut res = OpGetDo::new(self, header);
1469        res.request
1470            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
1471        res
1472    }
1473}
1474#[cfg(test)]
1475mod generated_tests {
1476    use super::*;
1477    #[test]
1478    fn tests() {
1479        let _ = IterableVport::get_ifindex;
1480        let _ = IterableVport::get_name;
1481        let _ = IterableVport::get_netnsid;
1482        let _ = IterableVport::get_port_no;
1483        let _ = IterableVport::get_stats;
1484        let _ = IterableVport::get_type;
1485        let _ = IterableVport::get_upcall_pid;
1486        let _ = IterableVport::get_upcall_stats;
1487        let _ = PushVport::<&mut Vec<u8>>::nested_options;
1488        let _ = PushVport::<&mut Vec<u8>>::push_ifindex;
1489        let _ = PushVport::<&mut Vec<u8>>::push_name;
1490        let _ = PushVport::<&mut Vec<u8>>::push_port_no;
1491        let _ = PushVport::<&mut Vec<u8>>::push_type;
1492        let _ = PushVport::<&mut Vec<u8>>::push_upcall_pid;
1493    }
1494}