Skip to main content

netlink_bindings/ovs_datapath/
mod.rs

1#![doc = "OVS datapath 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_datapath";
17pub const PROTONAME_CSTR: &CStr = c"ovs_datapath";
18#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
19#[derive(Debug, Clone, Copy)]
20pub enum UserFeatures {
21    #[doc = "Allow last Netlink attribute to be unaligned\n"]
22    Unaligned = 1 << 0,
23    #[doc = "Allow datapath to associate multiple Netlink PIDs to each vport\n"]
24    VportPids = 1 << 1,
25    #[doc = "Allow tc offload recirc sharing\n"]
26    TcRecircSharing = 1 << 2,
27    #[doc = "Allow per-cpu dispatch of upcalls\n"]
28    DispatchUpcallPerCpu = 1 << 3,
29}
30impl UserFeatures {
31    pub fn from_value(value: u64) -> Option<Self> {
32        Some(match value {
33            n if n == 1 << 0 => Self::Unaligned,
34            n if n == 1 << 1 => Self::VportPids,
35            n if n == 1 << 2 => Self::TcRecircSharing,
36            n if n == 1 << 3 => Self::DispatchUpcallPerCpu,
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 OvsDpStats {
109    pub n_hit: u64,
110    pub n_missed: u64,
111    pub n_lost: u64,
112    pub n_flows: u64,
113}
114impl Clone for OvsDpStats {
115    fn clone(&self) -> Self {
116        Self::new_from_array(*self.as_array())
117    }
118}
119#[doc = "Create zero-initialized struct"]
120impl Default for OvsDpStats {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125impl OvsDpStats {
126    #[doc = "Create zero-initialized struct"]
127    pub fn new() -> Self {
128        Self::new_from_array([0u8; Self::len()])
129    }
130    #[doc = "Copy from contents from slice"]
131    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
132        if other.len() != Self::len() {
133            return None;
134        }
135        let mut buf = [0u8; Self::len()];
136        buf.clone_from_slice(other);
137        Some(Self::new_from_array(buf))
138    }
139    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
140    pub fn new_from_zeroed(other: &[u8]) -> Self {
141        let mut buf = [0u8; Self::len()];
142        let len = buf.len().min(other.len());
143        buf[..len].clone_from_slice(&other[..len]);
144        Self::new_from_array(buf)
145    }
146    pub fn new_from_array(buf: [u8; 32usize]) -> Self {
147        unsafe { std::mem::transmute(buf) }
148    }
149    pub fn as_slice(&self) -> &[u8] {
150        unsafe {
151            let ptr: *const u8 = std::mem::transmute(self as *const Self);
152            std::slice::from_raw_parts(ptr, Self::len())
153        }
154    }
155    pub fn from_slice(buf: &[u8]) -> &Self {
156        assert!(buf.len() >= Self::len());
157        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
158        unsafe { std::mem::transmute(buf.as_ptr()) }
159    }
160    pub fn as_array(&self) -> &[u8; 32usize] {
161        unsafe { std::mem::transmute(self) }
162    }
163    pub fn from_array(buf: &[u8; 32usize]) -> &Self {
164        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
165        unsafe { std::mem::transmute(buf) }
166    }
167    pub fn into_array(self) -> [u8; 32usize] {
168        unsafe { std::mem::transmute(self) }
169    }
170    pub const fn len() -> usize {
171        const _: () = assert!(std::mem::size_of::<OvsDpStats>() == 32usize);
172        32usize
173    }
174}
175impl std::fmt::Debug for OvsDpStats {
176    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177        fmt.debug_struct("OvsDpStats")
178            .field("n_hit", &{ self.n_hit })
179            .field("n_missed", &{ self.n_missed })
180            .field("n_lost", &{ self.n_lost })
181            .field("n_flows", &{ self.n_flows })
182            .finish()
183    }
184}
185#[repr(C, packed(4))]
186pub struct OvsDpMegaflowStats {
187    pub n_mask_hit: u64,
188    pub n_masks: u32,
189    pub padding: u32,
190    pub n_cache_hit: u64,
191    pub pad1: u64,
192}
193impl Clone for OvsDpMegaflowStats {
194    fn clone(&self) -> Self {
195        Self::new_from_array(*self.as_array())
196    }
197}
198#[doc = "Create zero-initialized struct"]
199impl Default for OvsDpMegaflowStats {
200    fn default() -> Self {
201        Self::new()
202    }
203}
204impl OvsDpMegaflowStats {
205    #[doc = "Create zero-initialized struct"]
206    pub fn new() -> Self {
207        Self::new_from_array([0u8; Self::len()])
208    }
209    #[doc = "Copy from contents from slice"]
210    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
211        if other.len() != Self::len() {
212            return None;
213        }
214        let mut buf = [0u8; Self::len()];
215        buf.clone_from_slice(other);
216        Some(Self::new_from_array(buf))
217    }
218    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
219    pub fn new_from_zeroed(other: &[u8]) -> Self {
220        let mut buf = [0u8; Self::len()];
221        let len = buf.len().min(other.len());
222        buf[..len].clone_from_slice(&other[..len]);
223        Self::new_from_array(buf)
224    }
225    pub fn new_from_array(buf: [u8; 32usize]) -> Self {
226        unsafe { std::mem::transmute(buf) }
227    }
228    pub fn as_slice(&self) -> &[u8] {
229        unsafe {
230            let ptr: *const u8 = std::mem::transmute(self as *const Self);
231            std::slice::from_raw_parts(ptr, Self::len())
232        }
233    }
234    pub fn from_slice(buf: &[u8]) -> &Self {
235        assert!(buf.len() >= Self::len());
236        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
237        unsafe { std::mem::transmute(buf.as_ptr()) }
238    }
239    pub fn as_array(&self) -> &[u8; 32usize] {
240        unsafe { std::mem::transmute(self) }
241    }
242    pub fn from_array(buf: &[u8; 32usize]) -> &Self {
243        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
244        unsafe { std::mem::transmute(buf) }
245    }
246    pub fn into_array(self) -> [u8; 32usize] {
247        unsafe { std::mem::transmute(self) }
248    }
249    pub const fn len() -> usize {
250        const _: () = assert!(std::mem::size_of::<OvsDpMegaflowStats>() == 32usize);
251        32usize
252    }
253}
254impl std::fmt::Debug for OvsDpMegaflowStats {
255    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        fmt.debug_struct("OvsDpMegaflowStats")
257            .field("n_mask_hit", &{ self.n_mask_hit })
258            .field("n_masks", &self.n_masks)
259            .field("padding", &self.padding)
260            .field("n_cache_hit", &{ self.n_cache_hit })
261            .field("pad1", &{ self.pad1 })
262            .finish()
263    }
264}
265#[derive(Clone)]
266pub enum Datapath<'a> {
267    Name(&'a CStr),
268    #[doc = "upcall pid\n"]
269    UpcallPid(u32),
270    Stats(OvsDpStats),
271    MegaflowStats(OvsDpMegaflowStats),
272    #[doc = "Associated type: [`UserFeatures`] (1 bit per enumeration)"]
273    UserFeatures(u32),
274    MasksCacheSize(u32),
275    PerCpuPids(&'a [u8]),
276    Ifindex(u32),
277}
278impl<'a> IterableDatapath<'a> {
279    pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
280        let mut iter = self.clone();
281        iter.pos = 0;
282        for attr in iter {
283            if let Ok(Datapath::Name(val)) = attr {
284                return Ok(val);
285            }
286        }
287        Err(ErrorContext::new_missing(
288            "Datapath",
289            "Name",
290            self.orig_loc,
291            self.buf.as_ptr() as usize,
292        ))
293    }
294    #[doc = "upcall pid\n"]
295    pub fn get_upcall_pid(&self) -> Result<u32, ErrorContext> {
296        let mut iter = self.clone();
297        iter.pos = 0;
298        for attr in iter {
299            if let Ok(Datapath::UpcallPid(val)) = attr {
300                return Ok(val);
301            }
302        }
303        Err(ErrorContext::new_missing(
304            "Datapath",
305            "UpcallPid",
306            self.orig_loc,
307            self.buf.as_ptr() as usize,
308        ))
309    }
310    pub fn get_stats(&self) -> Result<OvsDpStats, ErrorContext> {
311        let mut iter = self.clone();
312        iter.pos = 0;
313        for attr in iter {
314            if let Ok(Datapath::Stats(val)) = attr {
315                return Ok(val);
316            }
317        }
318        Err(ErrorContext::new_missing(
319            "Datapath",
320            "Stats",
321            self.orig_loc,
322            self.buf.as_ptr() as usize,
323        ))
324    }
325    pub fn get_megaflow_stats(&self) -> Result<OvsDpMegaflowStats, ErrorContext> {
326        let mut iter = self.clone();
327        iter.pos = 0;
328        for attr in iter {
329            if let Ok(Datapath::MegaflowStats(val)) = attr {
330                return Ok(val);
331            }
332        }
333        Err(ErrorContext::new_missing(
334            "Datapath",
335            "MegaflowStats",
336            self.orig_loc,
337            self.buf.as_ptr() as usize,
338        ))
339    }
340    #[doc = "Associated type: [`UserFeatures`] (1 bit per enumeration)"]
341    pub fn get_user_features(&self) -> Result<u32, ErrorContext> {
342        let mut iter = self.clone();
343        iter.pos = 0;
344        for attr in iter {
345            if let Ok(Datapath::UserFeatures(val)) = attr {
346                return Ok(val);
347            }
348        }
349        Err(ErrorContext::new_missing(
350            "Datapath",
351            "UserFeatures",
352            self.orig_loc,
353            self.buf.as_ptr() as usize,
354        ))
355    }
356    pub fn get_masks_cache_size(&self) -> Result<u32, ErrorContext> {
357        let mut iter = self.clone();
358        iter.pos = 0;
359        for attr in iter {
360            if let Ok(Datapath::MasksCacheSize(val)) = attr {
361                return Ok(val);
362            }
363        }
364        Err(ErrorContext::new_missing(
365            "Datapath",
366            "MasksCacheSize",
367            self.orig_loc,
368            self.buf.as_ptr() as usize,
369        ))
370    }
371    pub fn get_per_cpu_pids(&self) -> Result<&'a [u8], ErrorContext> {
372        let mut iter = self.clone();
373        iter.pos = 0;
374        for attr in iter {
375            if let Ok(Datapath::PerCpuPids(val)) = attr {
376                return Ok(val);
377            }
378        }
379        Err(ErrorContext::new_missing(
380            "Datapath",
381            "PerCpuPids",
382            self.orig_loc,
383            self.buf.as_ptr() as usize,
384        ))
385    }
386    pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
387        let mut iter = self.clone();
388        iter.pos = 0;
389        for attr in iter {
390            if let Ok(Datapath::Ifindex(val)) = attr {
391                return Ok(val);
392            }
393        }
394        Err(ErrorContext::new_missing(
395            "Datapath",
396            "Ifindex",
397            self.orig_loc,
398            self.buf.as_ptr() as usize,
399        ))
400    }
401}
402impl Datapath<'_> {
403    pub fn new<'a>(buf: &'a [u8]) -> IterableDatapath<'a> {
404        IterableDatapath::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            1u16 => "Name",
409            2u16 => "UpcallPid",
410            3u16 => "Stats",
411            4u16 => "MegaflowStats",
412            5u16 => "UserFeatures",
413            6u16 => "Pad",
414            7u16 => "MasksCacheSize",
415            8u16 => "PerCpuPids",
416            9u16 => "Ifindex",
417            _ => return None,
418        };
419        Some(res)
420    }
421}
422#[derive(Clone, Copy, Default)]
423pub struct IterableDatapath<'a> {
424    buf: &'a [u8],
425    pos: usize,
426    orig_loc: usize,
427}
428impl<'a> IterableDatapath<'a> {
429    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
430        Self {
431            buf,
432            pos: 0,
433            orig_loc,
434        }
435    }
436    pub fn get_buf(&self) -> &'a [u8] {
437        self.buf
438    }
439}
440impl<'a> Iterator for IterableDatapath<'a> {
441    type Item = Result<Datapath<'a>, ErrorContext>;
442    fn next(&mut self) -> Option<Self::Item> {
443        let mut pos;
444        let mut r#type;
445        loop {
446            pos = self.pos;
447            r#type = None;
448            if self.buf.len() == self.pos {
449                return None;
450            }
451            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
452                self.pos = self.buf.len();
453                break;
454            };
455            r#type = Some(header.r#type);
456            let res = match header.r#type {
457                1u16 => Datapath::Name({
458                    let res = CStr::from_bytes_with_nul(next).ok();
459                    let Some(val) = res else { break };
460                    val
461                }),
462                2u16 => Datapath::UpcallPid({
463                    let res = parse_u32(next);
464                    let Some(val) = res else { break };
465                    val
466                }),
467                3u16 => Datapath::Stats({
468                    let res = Some(OvsDpStats::new_from_zeroed(next));
469                    let Some(val) = res else { break };
470                    val
471                }),
472                4u16 => Datapath::MegaflowStats({
473                    let res = Some(OvsDpMegaflowStats::new_from_zeroed(next));
474                    let Some(val) = res else { break };
475                    val
476                }),
477                5u16 => Datapath::UserFeatures({
478                    let res = parse_u32(next);
479                    let Some(val) = res else { break };
480                    val
481                }),
482                7u16 => Datapath::MasksCacheSize({
483                    let res = parse_u32(next);
484                    let Some(val) = res else { break };
485                    val
486                }),
487                8u16 => Datapath::PerCpuPids({
488                    let res = Some(next);
489                    let Some(val) = res else { break };
490                    val
491                }),
492                9u16 => Datapath::Ifindex({
493                    let res = parse_u32(next);
494                    let Some(val) = res else { break };
495                    val
496                }),
497                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
498                n => continue,
499            };
500            return Some(Ok(res));
501        }
502        Some(Err(ErrorContext::new(
503            "Datapath",
504            r#type.and_then(|t| Datapath::attr_from_type(t)),
505            self.orig_loc,
506            self.buf.as_ptr().wrapping_add(pos) as usize,
507        )))
508    }
509}
510impl<'a> std::fmt::Debug for IterableDatapath<'_> {
511    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512        let mut fmt = f.debug_struct("Datapath");
513        for attr in self.clone() {
514            let attr = match attr {
515                Ok(a) => a,
516                Err(err) => {
517                    fmt.finish()?;
518                    f.write_str("Err(")?;
519                    err.fmt(f)?;
520                    return f.write_str(")");
521                }
522            };
523            match attr {
524                Datapath::Name(val) => fmt.field("Name", &val),
525                Datapath::UpcallPid(val) => fmt.field("UpcallPid", &val),
526                Datapath::Stats(val) => fmt.field("Stats", &val),
527                Datapath::MegaflowStats(val) => fmt.field("MegaflowStats", &val),
528                Datapath::UserFeatures(val) => fmt.field(
529                    "UserFeatures",
530                    &FormatFlags(val.into(), UserFeatures::from_value),
531                ),
532                Datapath::MasksCacheSize(val) => fmt.field("MasksCacheSize", &val),
533                Datapath::PerCpuPids(val) => fmt.field("PerCpuPids", &val),
534                Datapath::Ifindex(val) => fmt.field("Ifindex", &val),
535            };
536        }
537        fmt.finish()
538    }
539}
540impl IterableDatapath<'_> {
541    pub fn lookup_attr(
542        &self,
543        offset: usize,
544        missing_type: Option<u16>,
545    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
546        let mut stack = Vec::new();
547        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
548        if missing_type.is_some() && cur == offset {
549            stack.push(("Datapath", offset));
550            return (
551                stack,
552                missing_type.and_then(|t| Datapath::attr_from_type(t)),
553            );
554        }
555        if cur > offset || cur + self.buf.len() < offset {
556            return (stack, None);
557        }
558        let mut attrs = self.clone();
559        let mut last_off = cur + attrs.pos;
560        while let Some(attr) = attrs.next() {
561            let Ok(attr) = attr else { break };
562            match attr {
563                Datapath::Name(val) => {
564                    if last_off == offset {
565                        stack.push(("Name", last_off));
566                        break;
567                    }
568                }
569                Datapath::UpcallPid(val) => {
570                    if last_off == offset {
571                        stack.push(("UpcallPid", last_off));
572                        break;
573                    }
574                }
575                Datapath::Stats(val) => {
576                    if last_off == offset {
577                        stack.push(("Stats", last_off));
578                        break;
579                    }
580                }
581                Datapath::MegaflowStats(val) => {
582                    if last_off == offset {
583                        stack.push(("MegaflowStats", last_off));
584                        break;
585                    }
586                }
587                Datapath::UserFeatures(val) => {
588                    if last_off == offset {
589                        stack.push(("UserFeatures", last_off));
590                        break;
591                    }
592                }
593                Datapath::MasksCacheSize(val) => {
594                    if last_off == offset {
595                        stack.push(("MasksCacheSize", last_off));
596                        break;
597                    }
598                }
599                Datapath::PerCpuPids(val) => {
600                    if last_off == offset {
601                        stack.push(("PerCpuPids", last_off));
602                        break;
603                    }
604                }
605                Datapath::Ifindex(val) => {
606                    if last_off == offset {
607                        stack.push(("Ifindex", last_off));
608                        break;
609                    }
610                }
611                _ => {}
612            };
613            last_off = cur + attrs.pos;
614        }
615        if !stack.is_empty() {
616            stack.push(("Datapath", cur));
617        }
618        (stack, None)
619    }
620}
621pub struct PushDatapath<Prev: Pusher> {
622    pub(crate) prev: Option<Prev>,
623    pub(crate) header_offset: Option<usize>,
624}
625impl<Prev: Pusher> Pusher for PushDatapath<Prev> {
626    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
627        self.prev.as_mut().unwrap().as_vec_mut()
628    }
629    fn as_vec(&self) -> &Vec<u8> {
630        self.prev.as_ref().unwrap().as_vec()
631    }
632}
633impl<Prev: Pusher> PushDatapath<Prev> {
634    pub fn new(prev: Prev) -> Self {
635        Self {
636            prev: Some(prev),
637            header_offset: None,
638        }
639    }
640    pub fn end_nested(mut self) -> Prev {
641        let mut prev = self.prev.take().unwrap();
642        if let Some(header_offset) = &self.header_offset {
643            finalize_nested_header(prev.as_vec_mut(), *header_offset);
644        }
645        prev
646    }
647    pub fn push_name(mut self, value: &CStr) -> Self {
648        push_header(
649            self.as_vec_mut(),
650            1u16,
651            value.to_bytes_with_nul().len() as u16,
652        );
653        self.as_vec_mut().extend(value.to_bytes_with_nul());
654        self
655    }
656    pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
657        push_header(self.as_vec_mut(), 1u16, (value.len() + 1) as u16);
658        self.as_vec_mut().extend(value);
659        self.as_vec_mut().push(0);
660        self
661    }
662    #[doc = "upcall pid\n"]
663    pub fn push_upcall_pid(mut self, value: u32) -> Self {
664        push_header(self.as_vec_mut(), 2u16, 4 as u16);
665        self.as_vec_mut().extend(value.to_ne_bytes());
666        self
667    }
668    pub fn push_stats(mut self, value: OvsDpStats) -> Self {
669        push_header(self.as_vec_mut(), 3u16, value.as_slice().len() as u16);
670        self.as_vec_mut().extend(value.as_slice());
671        self
672    }
673    pub fn push_megaflow_stats(mut self, value: OvsDpMegaflowStats) -> Self {
674        push_header(self.as_vec_mut(), 4u16, value.as_slice().len() as u16);
675        self.as_vec_mut().extend(value.as_slice());
676        self
677    }
678    #[doc = "Associated type: [`UserFeatures`] (1 bit per enumeration)"]
679    pub fn push_user_features(mut self, value: u32) -> Self {
680        push_header(self.as_vec_mut(), 5u16, 4 as u16);
681        self.as_vec_mut().extend(value.to_ne_bytes());
682        self
683    }
684    pub fn push_masks_cache_size(mut self, value: u32) -> Self {
685        push_header(self.as_vec_mut(), 7u16, 4 as u16);
686        self.as_vec_mut().extend(value.to_ne_bytes());
687        self
688    }
689    pub fn push_per_cpu_pids(mut self, value: &[u8]) -> Self {
690        push_header(self.as_vec_mut(), 8u16, value.len() as u16);
691        self.as_vec_mut().extend(value);
692        self
693    }
694    pub fn push_ifindex(mut self, value: u32) -> Self {
695        push_header(self.as_vec_mut(), 9u16, 4 as u16);
696        self.as_vec_mut().extend(value.to_ne_bytes());
697        self
698    }
699}
700impl<Prev: Pusher> Drop for PushDatapath<Prev> {
701    fn drop(&mut self) {
702        if let Some(prev) = &mut self.prev {
703            if let Some(header_offset) = &self.header_offset {
704                finalize_nested_header(prev.as_vec_mut(), *header_offset);
705            }
706        }
707    }
708}
709pub struct NotifGroup;
710impl NotifGroup {
711    pub const OVS_DATAPATH: &str = "ovs_datapath";
712    pub const OVS_DATAPATH_CSTR: &CStr = c"ovs_datapath";
713}
714#[doc = "Get / dump OVS data path configuration and state\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\nReply attributes:\n- [.get_name()](IterableDatapath::get_name)\n- [.get_upcall_pid()](IterableDatapath::get_upcall_pid)\n- [.get_stats()](IterableDatapath::get_stats)\n- [.get_megaflow_stats()](IterableDatapath::get_megaflow_stats)\n- [.get_user_features()](IterableDatapath::get_user_features)\n- [.get_masks_cache_size()](IterableDatapath::get_masks_cache_size)\n- [.get_per_cpu_pids()](IterableDatapath::get_per_cpu_pids)\n\n"]
715#[derive(Debug)]
716pub struct OpGetDump<'r> {
717    request: Request<'r>,
718}
719impl<'r> OpGetDump<'r> {
720    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
721        Self::write_header(request.buf_mut(), header);
722        Self {
723            request: request.set_dump(),
724        }
725    }
726    pub fn encode_request<'buf>(
727        buf: &'buf mut Vec<u8>,
728        header: &OvsHeader,
729    ) -> PushDatapath<&'buf mut Vec<u8>> {
730        Self::write_header(buf, header);
731        PushDatapath::new(buf)
732    }
733    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
734        PushDatapath::new(self.request.buf_mut())
735    }
736    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
737        PushDatapath::new(self.request.buf)
738    }
739    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
740        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
741        (
742            OvsHeader::new_from_slice(header).unwrap_or_default(),
743            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
744        )
745    }
746    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &OvsHeader) {
747        prev.as_vec_mut().extend(header.as_slice());
748    }
749}
750impl NetlinkRequest for OpGetDump<'_> {
751    fn protocol(&self) -> Protocol {
752        Protocol::Generic("ovs_datapath".as_bytes())
753    }
754    fn flags(&self) -> u16 {
755        self.request.flags
756    }
757    fn payload(&self) -> &[u8] {
758        self.request.buf()
759    }
760    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
761    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
762        Self::decode_request(buf)
763    }
764    fn lookup(
765        buf: &[u8],
766        offset: usize,
767        missing_type: Option<u16>,
768    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
769        Self::decode_request(buf)
770            .1
771            .lookup_attr(offset, missing_type)
772    }
773}
774#[doc = "Get / dump OVS data path configuration and state\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\nReply attributes:\n- [.get_name()](IterableDatapath::get_name)\n- [.get_upcall_pid()](IterableDatapath::get_upcall_pid)\n- [.get_stats()](IterableDatapath::get_stats)\n- [.get_megaflow_stats()](IterableDatapath::get_megaflow_stats)\n- [.get_user_features()](IterableDatapath::get_user_features)\n- [.get_masks_cache_size()](IterableDatapath::get_masks_cache_size)\n- [.get_per_cpu_pids()](IterableDatapath::get_per_cpu_pids)\n\n"]
775#[derive(Debug)]
776pub struct OpGetDo<'r> {
777    request: Request<'r>,
778}
779impl<'r> OpGetDo<'r> {
780    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
781        Self::write_header(request.buf_mut(), header);
782        Self { request: request }
783    }
784    pub fn encode_request<'buf>(
785        buf: &'buf mut Vec<u8>,
786        header: &OvsHeader,
787    ) -> PushDatapath<&'buf mut Vec<u8>> {
788        Self::write_header(buf, header);
789        PushDatapath::new(buf)
790    }
791    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
792        PushDatapath::new(self.request.buf_mut())
793    }
794    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
795        PushDatapath::new(self.request.buf)
796    }
797    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
798        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
799        (
800            OvsHeader::new_from_slice(header).unwrap_or_default(),
801            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
802        )
803    }
804    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &OvsHeader) {
805        prev.as_vec_mut().extend(header.as_slice());
806    }
807}
808impl NetlinkRequest for OpGetDo<'_> {
809    fn protocol(&self) -> Protocol {
810        Protocol::Generic("ovs_datapath".as_bytes())
811    }
812    fn flags(&self) -> u16 {
813        self.request.flags
814    }
815    fn payload(&self) -> &[u8] {
816        self.request.buf()
817    }
818    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
819    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
820        Self::decode_request(buf)
821    }
822    fn lookup(
823        buf: &[u8],
824        offset: usize,
825        missing_type: Option<u16>,
826    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
827        Self::decode_request(buf)
828            .1
829            .lookup_attr(offset, missing_type)
830    }
831}
832#[doc = "Create new OVS data path\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n- [.push_upcall_pid()](PushDatapath::push_upcall_pid)\n- [.push_user_features()](PushDatapath::push_user_features)\n\n"]
833#[derive(Debug)]
834pub struct OpNewDo<'r> {
835    request: Request<'r>,
836}
837impl<'r> OpNewDo<'r> {
838    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
839        Self::write_header(request.buf_mut(), header);
840        Self { request: request }
841    }
842    pub fn encode_request<'buf>(
843        buf: &'buf mut Vec<u8>,
844        header: &OvsHeader,
845    ) -> PushDatapath<&'buf mut Vec<u8>> {
846        Self::write_header(buf, header);
847        PushDatapath::new(buf)
848    }
849    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
850        PushDatapath::new(self.request.buf_mut())
851    }
852    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
853        PushDatapath::new(self.request.buf)
854    }
855    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
856        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
857        (
858            OvsHeader::new_from_slice(header).unwrap_or_default(),
859            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
860        )
861    }
862    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &OvsHeader) {
863        prev.as_vec_mut().extend(header.as_slice());
864    }
865}
866impl NetlinkRequest for OpNewDo<'_> {
867    fn protocol(&self) -> Protocol {
868        Protocol::Generic("ovs_datapath".as_bytes())
869    }
870    fn flags(&self) -> u16 {
871        self.request.flags
872    }
873    fn payload(&self) -> &[u8] {
874        self.request.buf()
875    }
876    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
877    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
878        Self::decode_request(buf)
879    }
880    fn lookup(
881        buf: &[u8],
882        offset: usize,
883        missing_type: Option<u16>,
884    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
885        Self::decode_request(buf)
886            .1
887            .lookup_attr(offset, missing_type)
888    }
889}
890#[doc = "Delete existing OVS data path\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\n"]
891#[derive(Debug)]
892pub struct OpDelDo<'r> {
893    request: Request<'r>,
894}
895impl<'r> OpDelDo<'r> {
896    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
897        Self::write_header(request.buf_mut(), header);
898        Self { request: request }
899    }
900    pub fn encode_request<'buf>(
901        buf: &'buf mut Vec<u8>,
902        header: &OvsHeader,
903    ) -> PushDatapath<&'buf mut Vec<u8>> {
904        Self::write_header(buf, header);
905        PushDatapath::new(buf)
906    }
907    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
908        PushDatapath::new(self.request.buf_mut())
909    }
910    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
911        PushDatapath::new(self.request.buf)
912    }
913    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
914        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
915        (
916            OvsHeader::new_from_slice(header).unwrap_or_default(),
917            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
918        )
919    }
920    fn write_header<Prev: Pusher>(prev: &mut Prev, header: &OvsHeader) {
921        prev.as_vec_mut().extend(header.as_slice());
922    }
923}
924impl NetlinkRequest for OpDelDo<'_> {
925    fn protocol(&self) -> Protocol {
926        Protocol::Generic("ovs_datapath".as_bytes())
927    }
928    fn flags(&self) -> u16 {
929        self.request.flags
930    }
931    fn payload(&self) -> &[u8] {
932        self.request.buf()
933    }
934    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
935    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
936        Self::decode_request(buf)
937    }
938    fn lookup(
939        buf: &[u8],
940        offset: usize,
941        missing_type: Option<u16>,
942    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
943        Self::decode_request(buf)
944            .1
945            .lookup_attr(offset, missing_type)
946    }
947}
948use crate::traits::LookupFn;
949use crate::utils::RequestBuf;
950#[derive(Debug)]
951pub struct Request<'buf> {
952    buf: RequestBuf<'buf>,
953    flags: u16,
954    writeback: Option<&'buf mut Option<RequestInfo>>,
955}
956#[allow(unused)]
957#[derive(Debug, Clone)]
958pub struct RequestInfo {
959    protocol: Protocol,
960    flags: u16,
961    name: &'static str,
962    lookup: LookupFn,
963}
964impl Request<'static> {
965    pub fn new() -> Self {
966        Self::new_from_buf(Vec::new())
967    }
968    pub fn new_from_buf(buf: Vec<u8>) -> Self {
969        Self {
970            flags: 0,
971            buf: RequestBuf::Own(buf),
972            writeback: None,
973        }
974    }
975    pub fn into_buf(self) -> Vec<u8> {
976        match self.buf {
977            RequestBuf::Own(buf) => buf,
978            _ => unreachable!(),
979        }
980    }
981}
982impl<'buf> Request<'buf> {
983    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
984        buf.clear();
985        Self::new_extend(buf)
986    }
987    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
988        Self {
989            flags: 0,
990            buf: RequestBuf::Ref(buf),
991            writeback: None,
992        }
993    }
994    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
995        let Some(writeback) = &mut self.writeback else {
996            return;
997        };
998        **writeback = Some(RequestInfo {
999            protocol,
1000            flags: self.flags,
1001            name,
1002            lookup,
1003        })
1004    }
1005    pub fn buf(&self) -> &Vec<u8> {
1006        self.buf.buf()
1007    }
1008    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1009        self.buf.buf_mut()
1010    }
1011    #[doc = "Set `NLM_F_CREATE` flag"]
1012    pub fn set_create(mut self) -> Self {
1013        self.flags |= consts::NLM_F_CREATE as u16;
1014        self
1015    }
1016    #[doc = "Set `NLM_F_EXCL` flag"]
1017    pub fn set_excl(mut self) -> Self {
1018        self.flags |= consts::NLM_F_EXCL as u16;
1019        self
1020    }
1021    #[doc = "Set `NLM_F_REPLACE` flag"]
1022    pub fn set_replace(mut self) -> Self {
1023        self.flags |= consts::NLM_F_REPLACE as u16;
1024        self
1025    }
1026    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1027    pub fn set_change(self) -> Self {
1028        self.set_create().set_replace()
1029    }
1030    #[doc = "Set `NLM_F_APPEND` flag"]
1031    pub fn set_append(mut self) -> Self {
1032        self.flags |= consts::NLM_F_APPEND as u16;
1033        self
1034    }
1035    #[doc = "Set `self.flags |= flags`"]
1036    pub fn set_flags(mut self, flags: u16) -> Self {
1037        self.flags |= flags;
1038        self
1039    }
1040    #[doc = "Set `self.flags ^= self.flags & flags`"]
1041    pub fn unset_flags(mut self, flags: u16) -> Self {
1042        self.flags ^= self.flags & flags;
1043        self
1044    }
1045    #[doc = "Set `NLM_F_DUMP` flag"]
1046    fn set_dump(mut self) -> Self {
1047        self.flags |= consts::NLM_F_DUMP as u16;
1048        self
1049    }
1050    #[doc = "Get / dump OVS data path configuration and state\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\nReply attributes:\n- [.get_name()](IterableDatapath::get_name)\n- [.get_upcall_pid()](IterableDatapath::get_upcall_pid)\n- [.get_stats()](IterableDatapath::get_stats)\n- [.get_megaflow_stats()](IterableDatapath::get_megaflow_stats)\n- [.get_user_features()](IterableDatapath::get_user_features)\n- [.get_masks_cache_size()](IterableDatapath::get_masks_cache_size)\n- [.get_per_cpu_pids()](IterableDatapath::get_per_cpu_pids)\n\n"]
1051    pub fn op_get_dump(self, header: &OvsHeader) -> OpGetDump<'buf> {
1052        let mut res = OpGetDump::new(self, header);
1053        res.request
1054            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
1055        res
1056    }
1057    #[doc = "Get / dump OVS data path configuration and state\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\nReply attributes:\n- [.get_name()](IterableDatapath::get_name)\n- [.get_upcall_pid()](IterableDatapath::get_upcall_pid)\n- [.get_stats()](IterableDatapath::get_stats)\n- [.get_megaflow_stats()](IterableDatapath::get_megaflow_stats)\n- [.get_user_features()](IterableDatapath::get_user_features)\n- [.get_masks_cache_size()](IterableDatapath::get_masks_cache_size)\n- [.get_per_cpu_pids()](IterableDatapath::get_per_cpu_pids)\n\n"]
1058    pub fn op_get_do(self, header: &OvsHeader) -> OpGetDo<'buf> {
1059        let mut res = OpGetDo::new(self, header);
1060        res.request
1061            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
1062        res
1063    }
1064    #[doc = "Create new OVS data path\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n- [.push_upcall_pid()](PushDatapath::push_upcall_pid)\n- [.push_user_features()](PushDatapath::push_user_features)\n\n"]
1065    pub fn op_new_do(self, header: &OvsHeader) -> OpNewDo<'buf> {
1066        let mut res = OpNewDo::new(self, header);
1067        res.request
1068            .do_writeback(res.protocol(), "op-new-do", OpNewDo::lookup);
1069        res
1070    }
1071    #[doc = "Delete existing OVS data path\n\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n\n"]
1072    pub fn op_del_do(self, header: &OvsHeader) -> OpDelDo<'buf> {
1073        let mut res = OpDelDo::new(self, header);
1074        res.request
1075            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
1076        res
1077    }
1078}
1079#[cfg(test)]
1080mod generated_tests {
1081    use super::*;
1082    #[test]
1083    fn tests() {
1084        let _ = IterableDatapath::get_masks_cache_size;
1085        let _ = IterableDatapath::get_megaflow_stats;
1086        let _ = IterableDatapath::get_name;
1087        let _ = IterableDatapath::get_per_cpu_pids;
1088        let _ = IterableDatapath::get_stats;
1089        let _ = IterableDatapath::get_upcall_pid;
1090        let _ = IterableDatapath::get_user_features;
1091        let _ = PushDatapath::<&mut Vec<u8>>::push_name;
1092        let _ = PushDatapath::<&mut Vec<u8>>::push_upcall_pid;
1093        let _ = PushDatapath::<&mut Vec<u8>>::push_user_features;
1094    }
1095}