Skip to main content

netlink_bindings/ovs_datapath/
mod.rs

1#![doc = "OVS datapath configuration over generic netlink\\."]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "ovs_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"]
22    Unaligned = 1 << 0,
23    #[doc = "Allow datapath to associate multiple Netlink PIDs to each vport"]
24    VportPids = 1 << 1,
25    #[doc = "Allow tc offload recirc sharing"]
26    TcRecircSharing = 1 << 2,
27    #[doc = "Allow per\\-cpu dispatch of upcalls"]
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"]
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 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"]
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 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 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 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 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 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 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 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 pos = self.pos;
444        let mut r#type;
445        loop {
446            r#type = None;
447            if self.buf.len() == self.pos {
448                return None;
449            }
450            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
451                break;
452            };
453            r#type = Some(header.r#type);
454            let res = match header.r#type {
455                1u16 => Datapath::Name({
456                    let res = CStr::from_bytes_with_nul(next).ok();
457                    let Some(val) = res else { break };
458                    val
459                }),
460                2u16 => Datapath::UpcallPid({
461                    let res = parse_u32(next);
462                    let Some(val) = res else { break };
463                    val
464                }),
465                3u16 => Datapath::Stats({
466                    let res = Some(OvsDpStats::new_from_zeroed(next));
467                    let Some(val) = res else { break };
468                    val
469                }),
470                4u16 => Datapath::MegaflowStats({
471                    let res = Some(OvsDpMegaflowStats::new_from_zeroed(next));
472                    let Some(val) = res else { break };
473                    val
474                }),
475                5u16 => Datapath::UserFeatures({
476                    let res = parse_u32(next);
477                    let Some(val) = res else { break };
478                    val
479                }),
480                7u16 => Datapath::MasksCacheSize({
481                    let res = parse_u32(next);
482                    let Some(val) = res else { break };
483                    val
484                }),
485                8u16 => Datapath::PerCpuPids({
486                    let res = Some(next);
487                    let Some(val) = res else { break };
488                    val
489                }),
490                9u16 => Datapath::Ifindex({
491                    let res = parse_u32(next);
492                    let Some(val) = res else { break };
493                    val
494                }),
495                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
496                n => continue,
497            };
498            return Some(Ok(res));
499        }
500        Some(Err(ErrorContext::new(
501            "Datapath",
502            r#type.and_then(|t| Datapath::attr_from_type(t)),
503            self.orig_loc,
504            self.buf.as_ptr().wrapping_add(pos) as usize,
505        )))
506    }
507}
508impl<'a> std::fmt::Debug for IterableDatapath<'_> {
509    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
510        let mut fmt = f.debug_struct("Datapath");
511        for attr in self.clone() {
512            let attr = match attr {
513                Ok(a) => a,
514                Err(err) => {
515                    fmt.finish()?;
516                    f.write_str("Err(")?;
517                    err.fmt(f)?;
518                    return f.write_str(")");
519                }
520            };
521            match attr {
522                Datapath::Name(val) => fmt.field("Name", &val),
523                Datapath::UpcallPid(val) => fmt.field("UpcallPid", &val),
524                Datapath::Stats(val) => fmt.field("Stats", &val),
525                Datapath::MegaflowStats(val) => fmt.field("MegaflowStats", &val),
526                Datapath::UserFeatures(val) => fmt.field(
527                    "UserFeatures",
528                    &FormatFlags(val.into(), UserFeatures::from_value),
529                ),
530                Datapath::MasksCacheSize(val) => fmt.field("MasksCacheSize", &val),
531                Datapath::PerCpuPids(val) => fmt.field("PerCpuPids", &val),
532                Datapath::Ifindex(val) => fmt.field("Ifindex", &val),
533            };
534        }
535        fmt.finish()
536    }
537}
538impl IterableDatapath<'_> {
539    pub fn lookup_attr(
540        &self,
541        offset: usize,
542        missing_type: Option<u16>,
543    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
544        let mut stack = Vec::new();
545        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
546        if missing_type.is_some() && cur == offset {
547            stack.push(("Datapath", offset));
548            return (
549                stack,
550                missing_type.and_then(|t| Datapath::attr_from_type(t)),
551            );
552        }
553        if cur > offset || cur + self.buf.len() < offset {
554            return (stack, None);
555        }
556        let mut attrs = self.clone();
557        let mut last_off = cur + attrs.pos;
558        while let Some(attr) = attrs.next() {
559            let Ok(attr) = attr else { break };
560            match attr {
561                Datapath::Name(val) => {
562                    if last_off == offset {
563                        stack.push(("Name", last_off));
564                        break;
565                    }
566                }
567                Datapath::UpcallPid(val) => {
568                    if last_off == offset {
569                        stack.push(("UpcallPid", last_off));
570                        break;
571                    }
572                }
573                Datapath::Stats(val) => {
574                    if last_off == offset {
575                        stack.push(("Stats", last_off));
576                        break;
577                    }
578                }
579                Datapath::MegaflowStats(val) => {
580                    if last_off == offset {
581                        stack.push(("MegaflowStats", last_off));
582                        break;
583                    }
584                }
585                Datapath::UserFeatures(val) => {
586                    if last_off == offset {
587                        stack.push(("UserFeatures", last_off));
588                        break;
589                    }
590                }
591                Datapath::MasksCacheSize(val) => {
592                    if last_off == offset {
593                        stack.push(("MasksCacheSize", last_off));
594                        break;
595                    }
596                }
597                Datapath::PerCpuPids(val) => {
598                    if last_off == offset {
599                        stack.push(("PerCpuPids", last_off));
600                        break;
601                    }
602                }
603                Datapath::Ifindex(val) => {
604                    if last_off == offset {
605                        stack.push(("Ifindex", last_off));
606                        break;
607                    }
608                }
609                _ => {}
610            };
611            last_off = cur + attrs.pos;
612        }
613        if !stack.is_empty() {
614            stack.push(("Datapath", cur));
615        }
616        (stack, None)
617    }
618}
619pub struct PushDatapath<Prev: Rec> {
620    pub(crate) prev: Option<Prev>,
621    pub(crate) header_offset: Option<usize>,
622}
623impl<Prev: Rec> Rec for PushDatapath<Prev> {
624    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
625        self.prev.as_mut().unwrap().as_rec_mut()
626    }
627    fn as_rec(&self) -> &Vec<u8> {
628        self.prev.as_ref().unwrap().as_rec()
629    }
630}
631impl<Prev: Rec> PushDatapath<Prev> {
632    pub fn new(prev: Prev) -> Self {
633        Self {
634            prev: Some(prev),
635            header_offset: None,
636        }
637    }
638    pub fn end_nested(mut self) -> Prev {
639        let mut prev = self.prev.take().unwrap();
640        if let Some(header_offset) = &self.header_offset {
641            finalize_nested_header(prev.as_rec_mut(), *header_offset);
642        }
643        prev
644    }
645    pub fn push_name(mut self, value: &CStr) -> Self {
646        push_header(
647            self.as_rec_mut(),
648            1u16,
649            value.to_bytes_with_nul().len() as u16,
650        );
651        self.as_rec_mut().extend(value.to_bytes_with_nul());
652        self
653    }
654    pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
655        push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
656        self.as_rec_mut().extend(value);
657        self.as_rec_mut().push(0);
658        self
659    }
660    #[doc = "upcall pid"]
661    pub fn push_upcall_pid(mut self, value: u32) -> Self {
662        push_header(self.as_rec_mut(), 2u16, 4 as u16);
663        self.as_rec_mut().extend(value.to_ne_bytes());
664        self
665    }
666    pub fn push_stats(mut self, value: OvsDpStats) -> Self {
667        push_header(self.as_rec_mut(), 3u16, value.as_slice().len() as u16);
668        self.as_rec_mut().extend(value.as_slice());
669        self
670    }
671    pub fn push_megaflow_stats(mut self, value: OvsDpMegaflowStats) -> Self {
672        push_header(self.as_rec_mut(), 4u16, value.as_slice().len() as u16);
673        self.as_rec_mut().extend(value.as_slice());
674        self
675    }
676    #[doc = "Associated type: [`UserFeatures`] (1 bit per enumeration)"]
677    pub fn push_user_features(mut self, value: u32) -> Self {
678        push_header(self.as_rec_mut(), 5u16, 4 as u16);
679        self.as_rec_mut().extend(value.to_ne_bytes());
680        self
681    }
682    pub fn push_masks_cache_size(mut self, value: u32) -> Self {
683        push_header(self.as_rec_mut(), 7u16, 4 as u16);
684        self.as_rec_mut().extend(value.to_ne_bytes());
685        self
686    }
687    pub fn push_per_cpu_pids(mut self, value: &[u8]) -> Self {
688        push_header(self.as_rec_mut(), 8u16, value.len() as u16);
689        self.as_rec_mut().extend(value);
690        self
691    }
692    pub fn push_ifindex(mut self, value: u32) -> Self {
693        push_header(self.as_rec_mut(), 9u16, 4 as u16);
694        self.as_rec_mut().extend(value.to_ne_bytes());
695        self
696    }
697}
698impl<Prev: Rec> Drop for PushDatapath<Prev> {
699    fn drop(&mut self) {
700        if let Some(prev) = &mut self.prev {
701            if let Some(header_offset) = &self.header_offset {
702                finalize_nested_header(prev.as_rec_mut(), *header_offset);
703            }
704        }
705    }
706}
707pub struct NotifGroup;
708impl NotifGroup {
709    pub const OVS_DATAPATH: &str = "ovs_datapath";
710    pub const OVS_DATAPATH_CSTR: &CStr = c"ovs_datapath";
711}
712#[doc = "Get / dump OVS data path configuration and state\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"]
713#[derive(Debug)]
714pub struct OpGetDump<'r> {
715    request: Request<'r>,
716}
717impl<'r> OpGetDump<'r> {
718    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
719        Self::write_header(request.buf_mut(), header);
720        Self {
721            request: request.set_dump(),
722        }
723    }
724    pub fn encode_request<'buf>(
725        buf: &'buf mut Vec<u8>,
726        header: &OvsHeader,
727    ) -> PushDatapath<&'buf mut Vec<u8>> {
728        Self::write_header(buf, header);
729        PushDatapath::new(buf)
730    }
731    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
732        PushDatapath::new(self.request.buf_mut())
733    }
734    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
735        PushDatapath::new(self.request.buf)
736    }
737    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
738        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
739        (
740            OvsHeader::new_from_slice(header).unwrap_or_default(),
741            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
742        )
743    }
744    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
745        prev.as_rec_mut().extend(header.as_slice());
746    }
747}
748impl NetlinkRequest for OpGetDump<'_> {
749    fn protocol(&self) -> Protocol {
750        Protocol::Generic("ovs_datapath".as_bytes())
751    }
752    fn flags(&self) -> u16 {
753        self.request.flags
754    }
755    fn payload(&self) -> &[u8] {
756        self.request.buf()
757    }
758    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
759    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
760        Self::decode_request(buf)
761    }
762    fn lookup(
763        buf: &[u8],
764        offset: usize,
765        missing_type: Option<u16>,
766    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
767        Self::decode_request(buf)
768            .1
769            .lookup_attr(offset, missing_type)
770    }
771}
772#[doc = "Get / dump OVS data path configuration and state\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"]
773#[derive(Debug)]
774pub struct OpGetDo<'r> {
775    request: Request<'r>,
776}
777impl<'r> OpGetDo<'r> {
778    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
779        Self::write_header(request.buf_mut(), header);
780        Self { request: request }
781    }
782    pub fn encode_request<'buf>(
783        buf: &'buf mut Vec<u8>,
784        header: &OvsHeader,
785    ) -> PushDatapath<&'buf mut Vec<u8>> {
786        Self::write_header(buf, header);
787        PushDatapath::new(buf)
788    }
789    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
790        PushDatapath::new(self.request.buf_mut())
791    }
792    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
793        PushDatapath::new(self.request.buf)
794    }
795    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
796        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
797        (
798            OvsHeader::new_from_slice(header).unwrap_or_default(),
799            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
800        )
801    }
802    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
803        prev.as_rec_mut().extend(header.as_slice());
804    }
805}
806impl NetlinkRequest for OpGetDo<'_> {
807    fn protocol(&self) -> Protocol {
808        Protocol::Generic("ovs_datapath".as_bytes())
809    }
810    fn flags(&self) -> u16 {
811        self.request.flags
812    }
813    fn payload(&self) -> &[u8] {
814        self.request.buf()
815    }
816    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
817    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
818        Self::decode_request(buf)
819    }
820    fn lookup(
821        buf: &[u8],
822        offset: usize,
823        missing_type: Option<u16>,
824    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
825        Self::decode_request(buf)
826            .1
827            .lookup_attr(offset, missing_type)
828    }
829}
830#[doc = "Create new OVS data path\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"]
831#[derive(Debug)]
832pub struct OpNewDo<'r> {
833    request: Request<'r>,
834}
835impl<'r> OpNewDo<'r> {
836    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
837        Self::write_header(request.buf_mut(), header);
838        Self { request: request }
839    }
840    pub fn encode_request<'buf>(
841        buf: &'buf mut Vec<u8>,
842        header: &OvsHeader,
843    ) -> PushDatapath<&'buf mut Vec<u8>> {
844        Self::write_header(buf, header);
845        PushDatapath::new(buf)
846    }
847    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
848        PushDatapath::new(self.request.buf_mut())
849    }
850    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
851        PushDatapath::new(self.request.buf)
852    }
853    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
854        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
855        (
856            OvsHeader::new_from_slice(header).unwrap_or_default(),
857            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
858        )
859    }
860    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
861        prev.as_rec_mut().extend(header.as_slice());
862    }
863}
864impl NetlinkRequest for OpNewDo<'_> {
865    fn protocol(&self) -> Protocol {
866        Protocol::Generic("ovs_datapath".as_bytes())
867    }
868    fn flags(&self) -> u16 {
869        self.request.flags
870    }
871    fn payload(&self) -> &[u8] {
872        self.request.buf()
873    }
874    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
875    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
876        Self::decode_request(buf)
877    }
878    fn lookup(
879        buf: &[u8],
880        offset: usize,
881        missing_type: Option<u16>,
882    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
883        Self::decode_request(buf)
884            .1
885            .lookup_attr(offset, missing_type)
886    }
887}
888#[doc = "Delete existing OVS data path\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n"]
889#[derive(Debug)]
890pub struct OpDelDo<'r> {
891    request: Request<'r>,
892}
893impl<'r> OpDelDo<'r> {
894    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
895        Self::write_header(request.buf_mut(), header);
896        Self { request: request }
897    }
898    pub fn encode_request<'buf>(
899        buf: &'buf mut Vec<u8>,
900        header: &OvsHeader,
901    ) -> PushDatapath<&'buf mut Vec<u8>> {
902        Self::write_header(buf, header);
903        PushDatapath::new(buf)
904    }
905    pub fn encode(&mut self) -> PushDatapath<&mut Vec<u8>> {
906        PushDatapath::new(self.request.buf_mut())
907    }
908    pub fn into_encoder(self) -> PushDatapath<RequestBuf<'r>> {
909        PushDatapath::new(self.request.buf)
910    }
911    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterableDatapath<'a>) {
912        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
913        (
914            OvsHeader::new_from_slice(header).unwrap_or_default(),
915            IterableDatapath::with_loc(attrs, buf.as_ptr() as usize),
916        )
917    }
918    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
919        prev.as_rec_mut().extend(header.as_slice());
920    }
921}
922impl NetlinkRequest for OpDelDo<'_> {
923    fn protocol(&self) -> Protocol {
924        Protocol::Generic("ovs_datapath".as_bytes())
925    }
926    fn flags(&self) -> u16 {
927        self.request.flags
928    }
929    fn payload(&self) -> &[u8] {
930        self.request.buf()
931    }
932    type ReplyType<'buf> = (OvsHeader, IterableDatapath<'buf>);
933    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
934        Self::decode_request(buf)
935    }
936    fn lookup(
937        buf: &[u8],
938        offset: usize,
939        missing_type: Option<u16>,
940    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
941        Self::decode_request(buf)
942            .1
943            .lookup_attr(offset, missing_type)
944    }
945}
946use crate::traits::LookupFn;
947use crate::utils::RequestBuf;
948#[derive(Debug)]
949pub struct Request<'buf> {
950    buf: RequestBuf<'buf>,
951    flags: u16,
952    writeback: Option<&'buf mut Option<RequestInfo>>,
953}
954#[allow(unused)]
955#[derive(Debug, Clone)]
956pub struct RequestInfo {
957    protocol: Protocol,
958    flags: u16,
959    name: &'static str,
960    lookup: LookupFn,
961}
962impl Request<'static> {
963    pub fn new() -> Self {
964        Self::new_from_buf(Vec::new())
965    }
966    pub fn new_from_buf(buf: Vec<u8>) -> Self {
967        Self {
968            flags: 0,
969            buf: RequestBuf::Own(buf),
970            writeback: None,
971        }
972    }
973    pub fn into_buf(self) -> Vec<u8> {
974        match self.buf {
975            RequestBuf::Own(buf) => buf,
976            _ => unreachable!(),
977        }
978    }
979}
980impl<'buf> Request<'buf> {
981    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
982        buf.clear();
983        Self::new_extend(buf)
984    }
985    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
986        Self {
987            flags: 0,
988            buf: RequestBuf::Ref(buf),
989            writeback: None,
990        }
991    }
992    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
993        let Some(writeback) = &mut self.writeback else {
994            return;
995        };
996        **writeback = Some(RequestInfo {
997            protocol,
998            flags: self.flags,
999            name,
1000            lookup,
1001        })
1002    }
1003    pub fn buf(&self) -> &Vec<u8> {
1004        self.buf.buf()
1005    }
1006    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1007        self.buf.buf_mut()
1008    }
1009    #[doc = "Set `NLM_F_CREATE` flag"]
1010    pub fn set_create(mut self) -> Self {
1011        self.flags |= consts::NLM_F_CREATE as u16;
1012        self
1013    }
1014    #[doc = "Set `NLM_F_EXCL` flag"]
1015    pub fn set_excl(mut self) -> Self {
1016        self.flags |= consts::NLM_F_EXCL as u16;
1017        self
1018    }
1019    #[doc = "Set `NLM_F_REPLACE` flag"]
1020    pub fn set_replace(mut self) -> Self {
1021        self.flags |= consts::NLM_F_REPLACE as u16;
1022        self
1023    }
1024    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1025    pub fn set_change(self) -> Self {
1026        self.set_create().set_replace()
1027    }
1028    #[doc = "Set `NLM_F_APPEND` flag"]
1029    pub fn set_append(mut self) -> Self {
1030        self.flags |= consts::NLM_F_APPEND as u16;
1031        self
1032    }
1033    #[doc = "Set `self.flags |= flags`"]
1034    pub fn set_flags(mut self, flags: u16) -> Self {
1035        self.flags |= flags;
1036        self
1037    }
1038    #[doc = "Set `self.flags ^= self.flags & flags`"]
1039    pub fn unset_flags(mut self, flags: u16) -> Self {
1040        self.flags ^= self.flags & flags;
1041        self
1042    }
1043    #[doc = "Set `NLM_F_DUMP` flag"]
1044    fn set_dump(mut self) -> Self {
1045        self.flags |= consts::NLM_F_DUMP as u16;
1046        self
1047    }
1048    #[doc = "Get / dump OVS data path configuration and state\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"]
1049    pub fn op_get_dump(self, header: &OvsHeader) -> OpGetDump<'buf> {
1050        let mut res = OpGetDump::new(self, header);
1051        res.request
1052            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
1053        res
1054    }
1055    #[doc = "Get / dump OVS data path configuration and state\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"]
1056    pub fn op_get_do(self, header: &OvsHeader) -> OpGetDo<'buf> {
1057        let mut res = OpGetDo::new(self, header);
1058        res.request
1059            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
1060        res
1061    }
1062    #[doc = "Create new OVS data path\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"]
1063    pub fn op_new_do(self, header: &OvsHeader) -> OpNewDo<'buf> {
1064        let mut res = OpNewDo::new(self, header);
1065        res.request
1066            .do_writeback(res.protocol(), "op-new-do", OpNewDo::lookup);
1067        res
1068    }
1069    #[doc = "Delete existing OVS data path\nRequest attributes:\n- [.push_name()](PushDatapath::push_name)\n"]
1070    pub fn op_del_do(self, header: &OvsHeader) -> OpDelDo<'buf> {
1071        let mut res = OpDelDo::new(self, header);
1072        res.request
1073            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
1074        res
1075    }
1076}
1077#[cfg(test)]
1078mod generated_tests {
1079    use super::*;
1080    #[test]
1081    fn tests() {
1082        let _ = IterableDatapath::get_masks_cache_size;
1083        let _ = IterableDatapath::get_megaflow_stats;
1084        let _ = IterableDatapath::get_name;
1085        let _ = IterableDatapath::get_per_cpu_pids;
1086        let _ = IterableDatapath::get_stats;
1087        let _ = IterableDatapath::get_upcall_pid;
1088        let _ = IterableDatapath::get_user_features;
1089        let _ = PushDatapath::<&mut Vec<u8>>::push_name;
1090        let _ = PushDatapath::<&mut Vec<u8>>::push_upcall_pid;
1091        let _ = PushDatapath::<&mut Vec<u8>>::push_user_features;
1092    }
1093}