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