Skip to main content

netlink_bindings/ovs_packet/
mod.rs

1#![doc = "OVS packet execution over generic netlink.\n\nOnly OVS_PACKET_CMD_EXECUTE is exposed as a genl operation.\nOVS_PACKET_CMD_MISS and OVS_PACKET_CMD_ACTION are kernel-to-userspace\nupcalls sent via genlmsg_unicast() to the vport\\'s upcall_pid and have\nno associated genl_ops or multicast group.\n\nSeveral attributes in the attribute set (userdata, egress-tun-key, len)\nexist for the upcall path and are not used by the EXECUTE operation. For\nEXECUTE, packet, key, and actions are mandatory (kernel returns -EINVAL\nwithout them).\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_packet";
17pub const PROTONAME_CSTR: &CStr = c"ovs_packet";
18#[derive(Debug)]
19#[repr(C, packed(4))]
20pub struct OvsHeader {
21    pub dp_ifindex: u32,
22}
23impl Clone for OvsHeader {
24    fn clone(&self) -> Self {
25        Self::new_from_array(*self.as_array())
26    }
27}
28#[doc = "Create zero-initialized struct"]
29impl Default for OvsHeader {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34impl OvsHeader {
35    #[doc = "Create zero-initialized struct"]
36    pub fn new() -> Self {
37        Self::new_from_array([0u8; Self::len()])
38    }
39    #[doc = "Copy from contents from slice"]
40    pub fn new_from_slice(other: &[u8]) -> Option<Self> {
41        if other.len() != Self::len() {
42            return None;
43        }
44        let mut buf = [0u8; Self::len()];
45        buf.clone_from_slice(other);
46        Some(Self::new_from_array(buf))
47    }
48    #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
49    pub fn new_from_zeroed(other: &[u8]) -> Self {
50        let mut buf = [0u8; Self::len()];
51        let len = buf.len().min(other.len());
52        buf[..len].clone_from_slice(&other[..len]);
53        Self::new_from_array(buf)
54    }
55    pub fn new_from_array(buf: [u8; 4usize]) -> Self {
56        unsafe { std::mem::transmute(buf) }
57    }
58    pub fn as_slice(&self) -> &[u8] {
59        unsafe {
60            let ptr: *const u8 = std::mem::transmute(self as *const Self);
61            std::slice::from_raw_parts(ptr, Self::len())
62        }
63    }
64    pub fn from_slice(buf: &[u8]) -> &Self {
65        assert!(buf.len() >= Self::len());
66        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
67        unsafe { std::mem::transmute(buf.as_ptr()) }
68    }
69    pub fn as_array(&self) -> &[u8; 4usize] {
70        unsafe { std::mem::transmute(self) }
71    }
72    pub fn from_array(buf: &[u8; 4usize]) -> &Self {
73        assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
74        unsafe { std::mem::transmute(buf) }
75    }
76    pub fn into_array(self) -> [u8; 4usize] {
77        unsafe { std::mem::transmute(self) }
78    }
79    pub const fn len() -> usize {
80        const _: () = assert!(std::mem::size_of::<OvsHeader>() == 4usize);
81        4usize
82    }
83}
84#[derive(Clone)]
85pub enum Packet<'a> {
86    #[doc = "Packet data, from the start of the Ethernet header.\n"]
87    Packet(&'a [u8]),
88    #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
89    Key(&'a [u8]),
90    #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
91    Actions(&'a [u8]),
92    #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
93    Userdata(&'a [u8]),
94    #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
95    EgressTunKey(&'a [u8]),
96    #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
97    Probe(()),
98    #[doc = "Maximum received IP fragment size.\n"]
99    Mru(u16),
100    #[doc = "Packet size before truncation.\n"]
101    Len(u32),
102    #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
103    Hash(u64),
104    #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
105    UpcallPid(u32),
106}
107impl<'a> IterablePacket<'a> {
108    #[doc = "Packet data, from the start of the Ethernet header.\n"]
109    pub fn get_packet(&self) -> Result<&'a [u8], ErrorContext> {
110        let mut iter = self.clone();
111        iter.pos = 0;
112        for attr in iter {
113            if let Ok(Packet::Packet(val)) = attr {
114                return Ok(val);
115            }
116        }
117        Err(ErrorContext::new_missing(
118            "Packet",
119            "Packet",
120            self.orig_loc,
121            self.buf.as_ptr() as usize,
122        ))
123    }
124    #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
125    pub fn get_key(&self) -> Result<&'a [u8], ErrorContext> {
126        let mut iter = self.clone();
127        iter.pos = 0;
128        for attr in iter {
129            if let Ok(Packet::Key(val)) = attr {
130                return Ok(val);
131            }
132        }
133        Err(ErrorContext::new_missing(
134            "Packet",
135            "Key",
136            self.orig_loc,
137            self.buf.as_ptr() as usize,
138        ))
139    }
140    #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
141    pub fn get_actions(&self) -> Result<&'a [u8], ErrorContext> {
142        let mut iter = self.clone();
143        iter.pos = 0;
144        for attr in iter {
145            if let Ok(Packet::Actions(val)) = attr {
146                return Ok(val);
147            }
148        }
149        Err(ErrorContext::new_missing(
150            "Packet",
151            "Actions",
152            self.orig_loc,
153            self.buf.as_ptr() as usize,
154        ))
155    }
156    #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
157    pub fn get_userdata(&self) -> Result<&'a [u8], ErrorContext> {
158        let mut iter = self.clone();
159        iter.pos = 0;
160        for attr in iter {
161            if let Ok(Packet::Userdata(val)) = attr {
162                return Ok(val);
163            }
164        }
165        Err(ErrorContext::new_missing(
166            "Packet",
167            "Userdata",
168            self.orig_loc,
169            self.buf.as_ptr() as usize,
170        ))
171    }
172    #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
173    pub fn get_egress_tun_key(&self) -> Result<&'a [u8], ErrorContext> {
174        let mut iter = self.clone();
175        iter.pos = 0;
176        for attr in iter {
177            if let Ok(Packet::EgressTunKey(val)) = attr {
178                return Ok(val);
179            }
180        }
181        Err(ErrorContext::new_missing(
182            "Packet",
183            "EgressTunKey",
184            self.orig_loc,
185            self.buf.as_ptr() as usize,
186        ))
187    }
188    #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
189    pub fn get_probe(&self) -> Result<(), ErrorContext> {
190        let mut iter = self.clone();
191        iter.pos = 0;
192        for attr in iter {
193            if let Ok(Packet::Probe(val)) = attr {
194                return Ok(val);
195            }
196        }
197        Err(ErrorContext::new_missing(
198            "Packet",
199            "Probe",
200            self.orig_loc,
201            self.buf.as_ptr() as usize,
202        ))
203    }
204    #[doc = "Maximum received IP fragment size.\n"]
205    pub fn get_mru(&self) -> Result<u16, ErrorContext> {
206        let mut iter = self.clone();
207        iter.pos = 0;
208        for attr in iter {
209            if let Ok(Packet::Mru(val)) = attr {
210                return Ok(val);
211            }
212        }
213        Err(ErrorContext::new_missing(
214            "Packet",
215            "Mru",
216            self.orig_loc,
217            self.buf.as_ptr() as usize,
218        ))
219    }
220    #[doc = "Packet size before truncation.\n"]
221    pub fn get_len(&self) -> Result<u32, ErrorContext> {
222        let mut iter = self.clone();
223        iter.pos = 0;
224        for attr in iter {
225            if let Ok(Packet::Len(val)) = attr {
226                return Ok(val);
227            }
228        }
229        Err(ErrorContext::new_missing(
230            "Packet",
231            "Len",
232            self.orig_loc,
233            self.buf.as_ptr() as usize,
234        ))
235    }
236    #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
237    pub fn get_hash(&self) -> Result<u64, ErrorContext> {
238        let mut iter = self.clone();
239        iter.pos = 0;
240        for attr in iter {
241            if let Ok(Packet::Hash(val)) = attr {
242                return Ok(val);
243            }
244        }
245        Err(ErrorContext::new_missing(
246            "Packet",
247            "Hash",
248            self.orig_loc,
249            self.buf.as_ptr() as usize,
250        ))
251    }
252    #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
253    pub fn get_upcall_pid(&self) -> Result<u32, ErrorContext> {
254        let mut iter = self.clone();
255        iter.pos = 0;
256        for attr in iter {
257            if let Ok(Packet::UpcallPid(val)) = attr {
258                return Ok(val);
259            }
260        }
261        Err(ErrorContext::new_missing(
262            "Packet",
263            "UpcallPid",
264            self.orig_loc,
265            self.buf.as_ptr() as usize,
266        ))
267    }
268}
269impl Packet<'_> {
270    pub fn new<'a>(buf: &'a [u8]) -> IterablePacket<'a> {
271        IterablePacket::with_loc(buf, buf.as_ptr() as usize)
272    }
273    fn attr_from_type(r#type: u16) -> Option<&'static str> {
274        let res = match r#type {
275            1u16 => "Packet",
276            2u16 => "Key",
277            3u16 => "Actions",
278            4u16 => "Userdata",
279            5u16 => "EgressTunKey",
280            6u16 => "Unused1",
281            7u16 => "Unused2",
282            8u16 => "Probe",
283            9u16 => "Mru",
284            10u16 => "Len",
285            11u16 => "Hash",
286            12u16 => "UpcallPid",
287            _ => return None,
288        };
289        Some(res)
290    }
291}
292#[derive(Clone, Copy, Default)]
293pub struct IterablePacket<'a> {
294    buf: &'a [u8],
295    pos: usize,
296    orig_loc: usize,
297}
298impl<'a> IterablePacket<'a> {
299    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
300        Self {
301            buf,
302            pos: 0,
303            orig_loc,
304        }
305    }
306    pub fn get_buf(&self) -> &'a [u8] {
307        self.buf
308    }
309}
310impl<'a> Iterator for IterablePacket<'a> {
311    type Item = Result<Packet<'a>, ErrorContext>;
312    fn next(&mut self) -> Option<Self::Item> {
313        let mut pos;
314        let mut r#type;
315        loop {
316            pos = self.pos;
317            r#type = None;
318            if self.buf.len() == self.pos {
319                return None;
320            }
321            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
322                self.pos = self.buf.len();
323                break;
324            };
325            r#type = Some(header.r#type);
326            let res = match header.r#type {
327                1u16 => Packet::Packet({
328                    let res = Some(next);
329                    let Some(val) = res else { break };
330                    val
331                }),
332                2u16 => Packet::Key({
333                    let res = Some(next);
334                    let Some(val) = res else { break };
335                    val
336                }),
337                3u16 => Packet::Actions({
338                    let res = Some(next);
339                    let Some(val) = res else { break };
340                    val
341                }),
342                4u16 => Packet::Userdata({
343                    let res = Some(next);
344                    let Some(val) = res else { break };
345                    val
346                }),
347                5u16 => Packet::EgressTunKey({
348                    let res = Some(next);
349                    let Some(val) = res else { break };
350                    val
351                }),
352                8u16 => Packet::Probe(()),
353                9u16 => Packet::Mru({
354                    let res = parse_u16(next);
355                    let Some(val) = res else { break };
356                    val
357                }),
358                10u16 => Packet::Len({
359                    let res = parse_u32(next);
360                    let Some(val) = res else { break };
361                    val
362                }),
363                11u16 => Packet::Hash({
364                    let res = parse_u64(next);
365                    let Some(val) = res else { break };
366                    val
367                }),
368                12u16 => Packet::UpcallPid({
369                    let res = parse_u32(next);
370                    let Some(val) = res else { break };
371                    val
372                }),
373                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
374                n => continue,
375            };
376            return Some(Ok(res));
377        }
378        Some(Err(ErrorContext::new(
379            "Packet",
380            r#type.and_then(|t| Packet::attr_from_type(t)),
381            self.orig_loc,
382            self.buf.as_ptr().wrapping_add(pos) as usize,
383        )))
384    }
385}
386impl<'a> std::fmt::Debug for IterablePacket<'_> {
387    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388        let mut fmt = f.debug_struct("Packet");
389        for attr in self.clone() {
390            let attr = match attr {
391                Ok(a) => a,
392                Err(err) => {
393                    fmt.finish()?;
394                    f.write_str("Err(")?;
395                    err.fmt(f)?;
396                    return f.write_str(")");
397                }
398            };
399            match attr {
400                Packet::Packet(val) => fmt.field("Packet", &val),
401                Packet::Key(val) => fmt.field("Key", &val),
402                Packet::Actions(val) => fmt.field("Actions", &val),
403                Packet::Userdata(val) => fmt.field("Userdata", &val),
404                Packet::EgressTunKey(val) => fmt.field("EgressTunKey", &val),
405                Packet::Probe(val) => fmt.field("Probe", &val),
406                Packet::Mru(val) => fmt.field("Mru", &val),
407                Packet::Len(val) => fmt.field("Len", &val),
408                Packet::Hash(val) => fmt.field("Hash", &val),
409                Packet::UpcallPid(val) => fmt.field("UpcallPid", &val),
410            };
411        }
412        fmt.finish()
413    }
414}
415impl IterablePacket<'_> {
416    pub fn lookup_attr(
417        &self,
418        offset: usize,
419        missing_type: Option<u16>,
420    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
421        let mut stack = Vec::new();
422        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
423        if missing_type.is_some() && cur == offset {
424            stack.push(("Packet", offset));
425            return (stack, missing_type.and_then(|t| Packet::attr_from_type(t)));
426        }
427        if cur > offset || cur + self.buf.len() < offset {
428            return (stack, None);
429        }
430        let mut attrs = self.clone();
431        let mut last_off = cur + attrs.pos;
432        while let Some(attr) = attrs.next() {
433            let Ok(attr) = attr else { break };
434            match attr {
435                Packet::Packet(val) => {
436                    if last_off == offset {
437                        stack.push(("Packet", last_off));
438                        break;
439                    }
440                }
441                Packet::Key(val) => {
442                    if last_off == offset {
443                        stack.push(("Key", last_off));
444                        break;
445                    }
446                }
447                Packet::Actions(val) => {
448                    if last_off == offset {
449                        stack.push(("Actions", last_off));
450                        break;
451                    }
452                }
453                Packet::Userdata(val) => {
454                    if last_off == offset {
455                        stack.push(("Userdata", last_off));
456                        break;
457                    }
458                }
459                Packet::EgressTunKey(val) => {
460                    if last_off == offset {
461                        stack.push(("EgressTunKey", last_off));
462                        break;
463                    }
464                }
465                Packet::Probe(val) => {
466                    if last_off == offset {
467                        stack.push(("Probe", last_off));
468                        break;
469                    }
470                }
471                Packet::Mru(val) => {
472                    if last_off == offset {
473                        stack.push(("Mru", last_off));
474                        break;
475                    }
476                }
477                Packet::Len(val) => {
478                    if last_off == offset {
479                        stack.push(("Len", last_off));
480                        break;
481                    }
482                }
483                Packet::Hash(val) => {
484                    if last_off == offset {
485                        stack.push(("Hash", last_off));
486                        break;
487                    }
488                }
489                Packet::UpcallPid(val) => {
490                    if last_off == offset {
491                        stack.push(("UpcallPid", last_off));
492                        break;
493                    }
494                }
495                _ => {}
496            };
497            last_off = cur + attrs.pos;
498        }
499        if !stack.is_empty() {
500            stack.push(("Packet", cur));
501        }
502        (stack, None)
503    }
504}
505pub struct PushPacket<Prev: Rec> {
506    pub(crate) prev: Option<Prev>,
507    pub(crate) header_offset: Option<usize>,
508}
509impl<Prev: Rec> Rec for PushPacket<Prev> {
510    fn as_rec_mut(&mut self) -> &mut Vec<u8> {
511        self.prev.as_mut().unwrap().as_rec_mut()
512    }
513    fn as_rec(&self) -> &Vec<u8> {
514        self.prev.as_ref().unwrap().as_rec()
515    }
516}
517impl<Prev: Rec> PushPacket<Prev> {
518    pub fn new(prev: Prev) -> Self {
519        Self {
520            prev: Some(prev),
521            header_offset: None,
522        }
523    }
524    pub fn end_nested(mut self) -> Prev {
525        let mut prev = self.prev.take().unwrap();
526        if let Some(header_offset) = &self.header_offset {
527            finalize_nested_header(prev.as_rec_mut(), *header_offset);
528        }
529        prev
530    }
531    #[doc = "Packet data, from the start of the Ethernet header.\n"]
532    pub fn push_packet(mut self, value: &[u8]) -> Self {
533        push_header(self.as_rec_mut(), 1u16, value.len() as u16);
534        self.as_rec_mut().extend(value);
535        self
536    }
537    #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
538    pub fn push_key(mut self, value: &[u8]) -> Self {
539        push_header(self.as_rec_mut(), 2u16, value.len() as u16);
540        self.as_rec_mut().extend(value);
541        self
542    }
543    #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
544    pub fn push_actions(mut self, value: &[u8]) -> Self {
545        push_header(self.as_rec_mut(), 3u16, value.len() as u16);
546        self.as_rec_mut().extend(value);
547        self
548    }
549    #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
550    pub fn push_userdata(mut self, value: &[u8]) -> Self {
551        push_header(self.as_rec_mut(), 4u16, value.len() as u16);
552        self.as_rec_mut().extend(value);
553        self
554    }
555    #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
556    pub fn push_egress_tun_key(mut self, value: &[u8]) -> Self {
557        push_header(self.as_rec_mut(), 5u16, value.len() as u16);
558        self.as_rec_mut().extend(value);
559        self
560    }
561    #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
562    pub fn push_probe(mut self, value: ()) -> Self {
563        push_header(self.as_rec_mut(), 8u16, 0 as u16);
564        self
565    }
566    #[doc = "Maximum received IP fragment size.\n"]
567    pub fn push_mru(mut self, value: u16) -> Self {
568        push_header(self.as_rec_mut(), 9u16, 2 as u16);
569        self.as_rec_mut().extend(value.to_ne_bytes());
570        self
571    }
572    #[doc = "Packet size before truncation.\n"]
573    pub fn push_len(mut self, value: u32) -> Self {
574        push_header(self.as_rec_mut(), 10u16, 4 as u16);
575        self.as_rec_mut().extend(value.to_ne_bytes());
576        self
577    }
578    #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
579    pub fn push_hash(mut self, value: u64) -> Self {
580        push_header(self.as_rec_mut(), 11u16, 8 as u16);
581        self.as_rec_mut().extend(value.to_ne_bytes());
582        self
583    }
584    #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
585    pub fn push_upcall_pid(mut self, value: u32) -> Self {
586        push_header(self.as_rec_mut(), 12u16, 4 as u16);
587        self.as_rec_mut().extend(value.to_ne_bytes());
588        self
589    }
590}
591impl<Prev: Rec> Drop for PushPacket<Prev> {
592    fn drop(&mut self) {
593        if let Some(prev) = &mut self.prev {
594            if let Some(header_offset) = &self.header_offset {
595                finalize_nested_header(prev.as_rec_mut(), *header_offset);
596            }
597        }
598    }
599}
600#[doc = "Apply actions to a packet.\n\nRequest attributes:\n- [.push_packet()](PushPacket::push_packet)\n- [.push_key()](PushPacket::push_key)\n- [.push_actions()](PushPacket::push_actions)\n- [.push_probe()](PushPacket::push_probe)\n- [.push_mru()](PushPacket::push_mru)\n- [.push_hash()](PushPacket::push_hash)\n- [.push_upcall_pid()](PushPacket::push_upcall_pid)\n\n"]
601#[derive(Debug)]
602pub struct OpExecuteDo<'r> {
603    request: Request<'r>,
604}
605impl<'r> OpExecuteDo<'r> {
606    pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
607        Self::write_header(request.buf_mut(), header);
608        Self { request: request }
609    }
610    pub fn encode_request<'buf>(
611        buf: &'buf mut Vec<u8>,
612        header: &OvsHeader,
613    ) -> PushPacket<&'buf mut Vec<u8>> {
614        Self::write_header(buf, header);
615        PushPacket::new(buf)
616    }
617    pub fn encode(&mut self) -> PushPacket<&mut Vec<u8>> {
618        PushPacket::new(self.request.buf_mut())
619    }
620    pub fn into_encoder(self) -> PushPacket<RequestBuf<'r>> {
621        PushPacket::new(self.request.buf)
622    }
623    pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterablePacket<'a>) {
624        let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
625        (
626            OvsHeader::new_from_slice(header).unwrap_or_default(),
627            IterablePacket::with_loc(attrs, buf.as_ptr() as usize),
628        )
629    }
630    fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
631        prev.as_rec_mut().extend(header.as_slice());
632    }
633}
634impl NetlinkRequest for OpExecuteDo<'_> {
635    fn protocol(&self) -> Protocol {
636        Protocol::Generic("ovs_packet".as_bytes())
637    }
638    fn flags(&self) -> u16 {
639        self.request.flags
640    }
641    fn payload(&self) -> &[u8] {
642        self.request.buf()
643    }
644    type ReplyType<'buf> = (OvsHeader, IterablePacket<'buf>);
645    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
646        Self::decode_request(buf)
647    }
648    fn lookup(
649        buf: &[u8],
650        offset: usize,
651        missing_type: Option<u16>,
652    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
653        Self::decode_request(buf)
654            .1
655            .lookup_attr(offset, missing_type)
656    }
657}
658use crate::traits::LookupFn;
659use crate::utils::RequestBuf;
660#[derive(Debug)]
661pub struct Request<'buf> {
662    buf: RequestBuf<'buf>,
663    flags: u16,
664    writeback: Option<&'buf mut Option<RequestInfo>>,
665}
666#[allow(unused)]
667#[derive(Debug, Clone)]
668pub struct RequestInfo {
669    protocol: Protocol,
670    flags: u16,
671    name: &'static str,
672    lookup: LookupFn,
673}
674impl Request<'static> {
675    pub fn new() -> Self {
676        Self::new_from_buf(Vec::new())
677    }
678    pub fn new_from_buf(buf: Vec<u8>) -> Self {
679        Self {
680            flags: 0,
681            buf: RequestBuf::Own(buf),
682            writeback: None,
683        }
684    }
685    pub fn into_buf(self) -> Vec<u8> {
686        match self.buf {
687            RequestBuf::Own(buf) => buf,
688            _ => unreachable!(),
689        }
690    }
691}
692impl<'buf> Request<'buf> {
693    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
694        buf.clear();
695        Self::new_extend(buf)
696    }
697    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
698        Self {
699            flags: 0,
700            buf: RequestBuf::Ref(buf),
701            writeback: None,
702        }
703    }
704    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
705        let Some(writeback) = &mut self.writeback else {
706            return;
707        };
708        **writeback = Some(RequestInfo {
709            protocol,
710            flags: self.flags,
711            name,
712            lookup,
713        })
714    }
715    pub fn buf(&self) -> &Vec<u8> {
716        self.buf.buf()
717    }
718    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
719        self.buf.buf_mut()
720    }
721    #[doc = "Set `NLM_F_CREATE` flag"]
722    pub fn set_create(mut self) -> Self {
723        self.flags |= consts::NLM_F_CREATE as u16;
724        self
725    }
726    #[doc = "Set `NLM_F_EXCL` flag"]
727    pub fn set_excl(mut self) -> Self {
728        self.flags |= consts::NLM_F_EXCL as u16;
729        self
730    }
731    #[doc = "Set `NLM_F_REPLACE` flag"]
732    pub fn set_replace(mut self) -> Self {
733        self.flags |= consts::NLM_F_REPLACE as u16;
734        self
735    }
736    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
737    pub fn set_change(self) -> Self {
738        self.set_create().set_replace()
739    }
740    #[doc = "Set `NLM_F_APPEND` flag"]
741    pub fn set_append(mut self) -> Self {
742        self.flags |= consts::NLM_F_APPEND as u16;
743        self
744    }
745    #[doc = "Set `self.flags |= flags`"]
746    pub fn set_flags(mut self, flags: u16) -> Self {
747        self.flags |= flags;
748        self
749    }
750    #[doc = "Set `self.flags ^= self.flags & flags`"]
751    pub fn unset_flags(mut self, flags: u16) -> Self {
752        self.flags ^= self.flags & flags;
753        self
754    }
755    #[doc = "Apply actions to a packet.\n\nRequest attributes:\n- [.push_packet()](PushPacket::push_packet)\n- [.push_key()](PushPacket::push_key)\n- [.push_actions()](PushPacket::push_actions)\n- [.push_probe()](PushPacket::push_probe)\n- [.push_mru()](PushPacket::push_mru)\n- [.push_hash()](PushPacket::push_hash)\n- [.push_upcall_pid()](PushPacket::push_upcall_pid)\n\n"]
756    pub fn op_execute_do(self, header: &OvsHeader) -> OpExecuteDo<'buf> {
757        let mut res = OpExecuteDo::new(self, header);
758        res.request
759            .do_writeback(res.protocol(), "op-execute-do", OpExecuteDo::lookup);
760        res
761    }
762}
763#[cfg(test)]
764mod generated_tests {
765    use super::*;
766    #[test]
767    fn tests() {
768        let _ = PushPacket::<&mut Vec<u8>>::push_actions;
769        let _ = PushPacket::<&mut Vec<u8>>::push_hash;
770        let _ = PushPacket::<&mut Vec<u8>>::push_key;
771        let _ = PushPacket::<&mut Vec<u8>>::push_mru;
772        let _ = PushPacket::<&mut Vec<u8>>::push_packet;
773        let _ = PushPacket::<&mut Vec<u8>>::push_probe;
774        let _ = PushPacket::<&mut Vec<u8>>::push_upcall_pid;
775    }
776}