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