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