Skip to main content

netlink_bindings/ovs_vport/
mod.rs

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