1#![doc = "Network team device driver.\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 = "team";
17pub const PROTONAME_CSTR: &CStr = c"team";
18pub const STRING_MAX_LEN: u64 = 32u64;
19pub const GENL_CHANGE_EVENT_MC_GRP_NAME: &str = "change_event";
20pub const GENL_CHANGE_EVENT_MC_GRP_NAME_CSTR: &CStr = c"change_event";
21#[derive(Clone)]
22pub enum Team<'a> {
23 TeamIfindex(u32),
24 ListOption(IterableItemOption<'a>),
25 ListPort(IterableItemPort<'a>),
26}
27impl<'a> IterableTeam<'a> {
28 pub fn get_team_ifindex(&self) -> Result<u32, ErrorContext> {
29 let mut iter = self.clone();
30 iter.pos = 0;
31 for attr in iter {
32 if let Ok(Team::TeamIfindex(val)) = attr {
33 return Ok(val);
34 }
35 }
36 Err(ErrorContext::new_missing(
37 "Team",
38 "TeamIfindex",
39 self.orig_loc,
40 self.buf.as_ptr() as usize,
41 ))
42 }
43 pub fn get_list_option(&self) -> Result<IterableItemOption<'a>, ErrorContext> {
44 let mut iter = self.clone();
45 iter.pos = 0;
46 for attr in iter {
47 if let Ok(Team::ListOption(val)) = attr {
48 return Ok(val);
49 }
50 }
51 Err(ErrorContext::new_missing(
52 "Team",
53 "ListOption",
54 self.orig_loc,
55 self.buf.as_ptr() as usize,
56 ))
57 }
58 pub fn get_list_port(&self) -> Result<IterableItemPort<'a>, ErrorContext> {
59 let mut iter = self.clone();
60 iter.pos = 0;
61 for attr in iter {
62 if let Ok(Team::ListPort(val)) = attr {
63 return Ok(val);
64 }
65 }
66 Err(ErrorContext::new_missing(
67 "Team",
68 "ListPort",
69 self.orig_loc,
70 self.buf.as_ptr() as usize,
71 ))
72 }
73}
74impl Team<'_> {
75 pub fn new<'a>(buf: &'a [u8]) -> IterableTeam<'a> {
76 IterableTeam::with_loc(buf, buf.as_ptr() as usize)
77 }
78 fn attr_from_type(r#type: u16) -> Option<&'static str> {
79 let res = match r#type {
80 0u16 => "Unspec",
81 1u16 => "TeamIfindex",
82 2u16 => "ListOption",
83 3u16 => "ListPort",
84 _ => return None,
85 };
86 Some(res)
87 }
88}
89#[derive(Clone, Copy, Default)]
90pub struct IterableTeam<'a> {
91 buf: &'a [u8],
92 pos: usize,
93 orig_loc: usize,
94}
95impl<'a> IterableTeam<'a> {
96 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
97 Self {
98 buf,
99 pos: 0,
100 orig_loc,
101 }
102 }
103 pub fn get_buf(&self) -> &'a [u8] {
104 self.buf
105 }
106}
107impl<'a> Iterator for IterableTeam<'a> {
108 type Item = Result<Team<'a>, ErrorContext>;
109 fn next(&mut self) -> Option<Self::Item> {
110 let mut pos;
111 let mut r#type;
112 loop {
113 pos = self.pos;
114 r#type = None;
115 if self.buf.len() == self.pos {
116 return None;
117 }
118 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
119 self.pos = self.buf.len();
120 break;
121 };
122 r#type = Some(header.r#type);
123 let res = match header.r#type {
124 1u16 => Team::TeamIfindex({
125 let res = parse_u32(next);
126 let Some(val) = res else { break };
127 val
128 }),
129 2u16 => Team::ListOption({
130 let res = Some(IterableItemOption::with_loc(next, self.orig_loc));
131 let Some(val) = res else { break };
132 val
133 }),
134 3u16 => Team::ListPort({
135 let res = Some(IterableItemPort::with_loc(next, self.orig_loc));
136 let Some(val) = res else { break };
137 val
138 }),
139 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
140 n => continue,
141 };
142 return Some(Ok(res));
143 }
144 Some(Err(ErrorContext::new(
145 "Team",
146 r#type.and_then(|t| Team::attr_from_type(t)),
147 self.orig_loc,
148 self.buf.as_ptr().wrapping_add(pos) as usize,
149 )))
150 }
151}
152impl<'a> std::fmt::Debug for IterableTeam<'_> {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 let mut fmt = f.debug_struct("Team");
155 for attr in self.clone() {
156 let attr = match attr {
157 Ok(a) => a,
158 Err(err) => {
159 fmt.finish()?;
160 f.write_str("Err(")?;
161 err.fmt(f)?;
162 return f.write_str(")");
163 }
164 };
165 match attr {
166 Team::TeamIfindex(val) => fmt.field("TeamIfindex", &val),
167 Team::ListOption(val) => fmt.field("ListOption", &val),
168 Team::ListPort(val) => fmt.field("ListPort", &val),
169 };
170 }
171 fmt.finish()
172 }
173}
174impl IterableTeam<'_> {
175 pub fn lookup_attr(
176 &self,
177 offset: usize,
178 missing_type: Option<u16>,
179 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
180 let mut stack = Vec::new();
181 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
182 if missing_type.is_some() && cur == offset {
183 stack.push(("Team", offset));
184 return (stack, missing_type.and_then(|t| Team::attr_from_type(t)));
185 }
186 if cur > offset || cur + self.buf.len() < offset {
187 return (stack, None);
188 }
189 let mut attrs = self.clone();
190 let mut last_off = cur + attrs.pos;
191 let mut missing = None;
192 while let Some(attr) = attrs.next() {
193 let Ok(attr) = attr else { break };
194 match attr {
195 Team::TeamIfindex(val) => {
196 if last_off == offset {
197 stack.push(("TeamIfindex", last_off));
198 break;
199 }
200 }
201 Team::ListOption(val) => {
202 (stack, missing) = val.lookup_attr(offset, missing_type);
203 if !stack.is_empty() {
204 break;
205 }
206 }
207 Team::ListPort(val) => {
208 (stack, missing) = val.lookup_attr(offset, missing_type);
209 if !stack.is_empty() {
210 break;
211 }
212 }
213 _ => {}
214 };
215 last_off = cur + attrs.pos;
216 }
217 if !stack.is_empty() {
218 stack.push(("Team", cur));
219 }
220 (stack, missing)
221 }
222}
223#[derive(Clone)]
224pub enum ItemOption<'a> {
225 Option(IterableAttrOption<'a>),
226}
227impl<'a> IterableItemOption<'a> {
228 pub fn get_option(&self) -> Result<IterableAttrOption<'a>, ErrorContext> {
229 let mut iter = self.clone();
230 iter.pos = 0;
231 for attr in iter {
232 if let Ok(ItemOption::Option(val)) = attr {
233 return Ok(val);
234 }
235 }
236 Err(ErrorContext::new_missing(
237 "ItemOption",
238 "Option",
239 self.orig_loc,
240 self.buf.as_ptr() as usize,
241 ))
242 }
243}
244impl ItemOption<'_> {
245 pub fn new<'a>(buf: &'a [u8]) -> IterableItemOption<'a> {
246 IterableItemOption::with_loc(buf, buf.as_ptr() as usize)
247 }
248 fn attr_from_type(r#type: u16) -> Option<&'static str> {
249 let res = match r#type {
250 0u16 => "OptionUnspec",
251 1u16 => "Option",
252 _ => return None,
253 };
254 Some(res)
255 }
256}
257#[derive(Clone, Copy, Default)]
258pub struct IterableItemOption<'a> {
259 buf: &'a [u8],
260 pos: usize,
261 orig_loc: usize,
262}
263impl<'a> IterableItemOption<'a> {
264 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
265 Self {
266 buf,
267 pos: 0,
268 orig_loc,
269 }
270 }
271 pub fn get_buf(&self) -> &'a [u8] {
272 self.buf
273 }
274}
275impl<'a> Iterator for IterableItemOption<'a> {
276 type Item = Result<ItemOption<'a>, ErrorContext>;
277 fn next(&mut self) -> Option<Self::Item> {
278 let mut pos;
279 let mut r#type;
280 loop {
281 pos = self.pos;
282 r#type = None;
283 if self.buf.len() == self.pos {
284 return None;
285 }
286 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
287 self.pos = self.buf.len();
288 break;
289 };
290 r#type = Some(header.r#type);
291 let res = match header.r#type {
292 1u16 => ItemOption::Option({
293 let res = Some(IterableAttrOption::with_loc(next, self.orig_loc));
294 let Some(val) = res else { break };
295 val
296 }),
297 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
298 n => continue,
299 };
300 return Some(Ok(res));
301 }
302 Some(Err(ErrorContext::new(
303 "ItemOption",
304 r#type.and_then(|t| ItemOption::attr_from_type(t)),
305 self.orig_loc,
306 self.buf.as_ptr().wrapping_add(pos) as usize,
307 )))
308 }
309}
310impl<'a> std::fmt::Debug for IterableItemOption<'_> {
311 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
312 let mut fmt = f.debug_struct("ItemOption");
313 for attr in self.clone() {
314 let attr = match attr {
315 Ok(a) => a,
316 Err(err) => {
317 fmt.finish()?;
318 f.write_str("Err(")?;
319 err.fmt(f)?;
320 return f.write_str(")");
321 }
322 };
323 match attr {
324 ItemOption::Option(val) => fmt.field("Option", &val),
325 };
326 }
327 fmt.finish()
328 }
329}
330impl IterableItemOption<'_> {
331 pub fn lookup_attr(
332 &self,
333 offset: usize,
334 missing_type: Option<u16>,
335 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
336 let mut stack = Vec::new();
337 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
338 if missing_type.is_some() && cur == offset {
339 stack.push(("ItemOption", offset));
340 return (
341 stack,
342 missing_type.and_then(|t| ItemOption::attr_from_type(t)),
343 );
344 }
345 if cur > offset || cur + self.buf.len() < offset {
346 return (stack, None);
347 }
348 let mut attrs = self.clone();
349 let mut last_off = cur + attrs.pos;
350 let mut missing = None;
351 while let Some(attr) = attrs.next() {
352 let Ok(attr) = attr else { break };
353 match attr {
354 ItemOption::Option(val) => {
355 (stack, missing) = val.lookup_attr(offset, missing_type);
356 if !stack.is_empty() {
357 break;
358 }
359 }
360 _ => {}
361 };
362 last_off = cur + attrs.pos;
363 }
364 if !stack.is_empty() {
365 stack.push(("ItemOption", cur));
366 }
367 (stack, missing)
368 }
369}
370#[derive(Clone)]
371pub enum AttrOption<'a> {
372 Name(&'a CStr),
373 Changed(()),
374 Type(u8),
375 Data(&'a [u8]),
376 Removed(()),
377 #[doc = "for per-port options\n"]
378 PortIfindex(u32),
379 #[doc = "for array options\n"]
380 ArrayIndex(u32),
381}
382impl<'a> IterableAttrOption<'a> {
383 pub fn get_name(&self) -> Result<&'a CStr, ErrorContext> {
384 let mut iter = self.clone();
385 iter.pos = 0;
386 for attr in iter {
387 if let Ok(AttrOption::Name(val)) = attr {
388 return Ok(val);
389 }
390 }
391 Err(ErrorContext::new_missing(
392 "AttrOption",
393 "Name",
394 self.orig_loc,
395 self.buf.as_ptr() as usize,
396 ))
397 }
398 pub fn get_changed(&self) -> Result<(), ErrorContext> {
399 let mut iter = self.clone();
400 iter.pos = 0;
401 for attr in iter {
402 if let Ok(AttrOption::Changed(val)) = attr {
403 return Ok(val);
404 }
405 }
406 Err(ErrorContext::new_missing(
407 "AttrOption",
408 "Changed",
409 self.orig_loc,
410 self.buf.as_ptr() as usize,
411 ))
412 }
413 pub fn get_type(&self) -> Result<u8, ErrorContext> {
414 let mut iter = self.clone();
415 iter.pos = 0;
416 for attr in iter {
417 if let Ok(AttrOption::Type(val)) = attr {
418 return Ok(val);
419 }
420 }
421 Err(ErrorContext::new_missing(
422 "AttrOption",
423 "Type",
424 self.orig_loc,
425 self.buf.as_ptr() as usize,
426 ))
427 }
428 pub fn get_data(&self) -> Result<&'a [u8], ErrorContext> {
429 let mut iter = self.clone();
430 iter.pos = 0;
431 for attr in iter {
432 if let Ok(AttrOption::Data(val)) = attr {
433 return Ok(val);
434 }
435 }
436 Err(ErrorContext::new_missing(
437 "AttrOption",
438 "Data",
439 self.orig_loc,
440 self.buf.as_ptr() as usize,
441 ))
442 }
443 pub fn get_removed(&self) -> Result<(), ErrorContext> {
444 let mut iter = self.clone();
445 iter.pos = 0;
446 for attr in iter {
447 if let Ok(AttrOption::Removed(val)) = attr {
448 return Ok(val);
449 }
450 }
451 Err(ErrorContext::new_missing(
452 "AttrOption",
453 "Removed",
454 self.orig_loc,
455 self.buf.as_ptr() as usize,
456 ))
457 }
458 #[doc = "for per-port options\n"]
459 pub fn get_port_ifindex(&self) -> Result<u32, ErrorContext> {
460 let mut iter = self.clone();
461 iter.pos = 0;
462 for attr in iter {
463 if let Ok(AttrOption::PortIfindex(val)) = attr {
464 return Ok(val);
465 }
466 }
467 Err(ErrorContext::new_missing(
468 "AttrOption",
469 "PortIfindex",
470 self.orig_loc,
471 self.buf.as_ptr() as usize,
472 ))
473 }
474 #[doc = "for array options\n"]
475 pub fn get_array_index(&self) -> Result<u32, ErrorContext> {
476 let mut iter = self.clone();
477 iter.pos = 0;
478 for attr in iter {
479 if let Ok(AttrOption::ArrayIndex(val)) = attr {
480 return Ok(val);
481 }
482 }
483 Err(ErrorContext::new_missing(
484 "AttrOption",
485 "ArrayIndex",
486 self.orig_loc,
487 self.buf.as_ptr() as usize,
488 ))
489 }
490}
491impl AttrOption<'_> {
492 pub fn new<'a>(buf: &'a [u8]) -> IterableAttrOption<'a> {
493 IterableAttrOption::with_loc(buf, buf.as_ptr() as usize)
494 }
495 fn attr_from_type(r#type: u16) -> Option<&'static str> {
496 let res = match r#type {
497 0u16 => "Unspec",
498 1u16 => "Name",
499 2u16 => "Changed",
500 3u16 => "Type",
501 4u16 => "Data",
502 5u16 => "Removed",
503 6u16 => "PortIfindex",
504 7u16 => "ArrayIndex",
505 _ => return None,
506 };
507 Some(res)
508 }
509}
510#[derive(Clone, Copy, Default)]
511pub struct IterableAttrOption<'a> {
512 buf: &'a [u8],
513 pos: usize,
514 orig_loc: usize,
515}
516impl<'a> IterableAttrOption<'a> {
517 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
518 Self {
519 buf,
520 pos: 0,
521 orig_loc,
522 }
523 }
524 pub fn get_buf(&self) -> &'a [u8] {
525 self.buf
526 }
527}
528impl<'a> Iterator for IterableAttrOption<'a> {
529 type Item = Result<AttrOption<'a>, ErrorContext>;
530 fn next(&mut self) -> Option<Self::Item> {
531 let mut pos;
532 let mut r#type;
533 loop {
534 pos = self.pos;
535 r#type = None;
536 if self.buf.len() == self.pos {
537 return None;
538 }
539 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
540 self.pos = self.buf.len();
541 break;
542 };
543 r#type = Some(header.r#type);
544 let res = match header.r#type {
545 1u16 => AttrOption::Name({
546 let res = CStr::from_bytes_with_nul(next).ok();
547 let Some(val) = res else { break };
548 val
549 }),
550 2u16 => AttrOption::Changed(()),
551 3u16 => AttrOption::Type({
552 let res = parse_u8(next);
553 let Some(val) = res else { break };
554 val
555 }),
556 4u16 => AttrOption::Data({
557 let res = Some(next);
558 let Some(val) = res else { break };
559 val
560 }),
561 5u16 => AttrOption::Removed(()),
562 6u16 => AttrOption::PortIfindex({
563 let res = parse_u32(next);
564 let Some(val) = res else { break };
565 val
566 }),
567 7u16 => AttrOption::ArrayIndex({
568 let res = parse_u32(next);
569 let Some(val) = res else { break };
570 val
571 }),
572 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
573 n => continue,
574 };
575 return Some(Ok(res));
576 }
577 Some(Err(ErrorContext::new(
578 "AttrOption",
579 r#type.and_then(|t| AttrOption::attr_from_type(t)),
580 self.orig_loc,
581 self.buf.as_ptr().wrapping_add(pos) as usize,
582 )))
583 }
584}
585impl<'a> std::fmt::Debug for IterableAttrOption<'_> {
586 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
587 let mut fmt = f.debug_struct("AttrOption");
588 for attr in self.clone() {
589 let attr = match attr {
590 Ok(a) => a,
591 Err(err) => {
592 fmt.finish()?;
593 f.write_str("Err(")?;
594 err.fmt(f)?;
595 return f.write_str(")");
596 }
597 };
598 match attr {
599 AttrOption::Name(val) => fmt.field("Name", &val),
600 AttrOption::Changed(val) => fmt.field("Changed", &val),
601 AttrOption::Type(val) => fmt.field("Type", &val),
602 AttrOption::Data(val) => fmt.field("Data", &val),
603 AttrOption::Removed(val) => fmt.field("Removed", &val),
604 AttrOption::PortIfindex(val) => fmt.field("PortIfindex", &val),
605 AttrOption::ArrayIndex(val) => fmt.field("ArrayIndex", &val),
606 };
607 }
608 fmt.finish()
609 }
610}
611impl IterableAttrOption<'_> {
612 pub fn lookup_attr(
613 &self,
614 offset: usize,
615 missing_type: Option<u16>,
616 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
617 let mut stack = Vec::new();
618 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
619 if missing_type.is_some() && cur == offset {
620 stack.push(("AttrOption", offset));
621 return (
622 stack,
623 missing_type.and_then(|t| AttrOption::attr_from_type(t)),
624 );
625 }
626 if cur > offset || cur + self.buf.len() < offset {
627 return (stack, None);
628 }
629 let mut attrs = self.clone();
630 let mut last_off = cur + attrs.pos;
631 while let Some(attr) = attrs.next() {
632 let Ok(attr) = attr else { break };
633 match attr {
634 AttrOption::Name(val) => {
635 if last_off == offset {
636 stack.push(("Name", last_off));
637 break;
638 }
639 }
640 AttrOption::Changed(val) => {
641 if last_off == offset {
642 stack.push(("Changed", last_off));
643 break;
644 }
645 }
646 AttrOption::Type(val) => {
647 if last_off == offset {
648 stack.push(("Type", last_off));
649 break;
650 }
651 }
652 AttrOption::Data(val) => {
653 if last_off == offset {
654 stack.push(("Data", last_off));
655 break;
656 }
657 }
658 AttrOption::Removed(val) => {
659 if last_off == offset {
660 stack.push(("Removed", last_off));
661 break;
662 }
663 }
664 AttrOption::PortIfindex(val) => {
665 if last_off == offset {
666 stack.push(("PortIfindex", last_off));
667 break;
668 }
669 }
670 AttrOption::ArrayIndex(val) => {
671 if last_off == offset {
672 stack.push(("ArrayIndex", last_off));
673 break;
674 }
675 }
676 _ => {}
677 };
678 last_off = cur + attrs.pos;
679 }
680 if !stack.is_empty() {
681 stack.push(("AttrOption", cur));
682 }
683 (stack, None)
684 }
685}
686#[derive(Clone)]
687pub enum ItemPort<'a> {
688 Port(IterableAttrPort<'a>),
689}
690impl<'a> IterableItemPort<'a> {
691 pub fn get_port(&self) -> Result<IterableAttrPort<'a>, ErrorContext> {
692 let mut iter = self.clone();
693 iter.pos = 0;
694 for attr in iter {
695 if let Ok(ItemPort::Port(val)) = attr {
696 return Ok(val);
697 }
698 }
699 Err(ErrorContext::new_missing(
700 "ItemPort",
701 "Port",
702 self.orig_loc,
703 self.buf.as_ptr() as usize,
704 ))
705 }
706}
707impl ItemPort<'_> {
708 pub fn new<'a>(buf: &'a [u8]) -> IterableItemPort<'a> {
709 IterableItemPort::with_loc(buf, buf.as_ptr() as usize)
710 }
711 fn attr_from_type(r#type: u16) -> Option<&'static str> {
712 let res = match r#type {
713 0u16 => "PortUnspec",
714 1u16 => "Port",
715 _ => return None,
716 };
717 Some(res)
718 }
719}
720#[derive(Clone, Copy, Default)]
721pub struct IterableItemPort<'a> {
722 buf: &'a [u8],
723 pos: usize,
724 orig_loc: usize,
725}
726impl<'a> IterableItemPort<'a> {
727 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
728 Self {
729 buf,
730 pos: 0,
731 orig_loc,
732 }
733 }
734 pub fn get_buf(&self) -> &'a [u8] {
735 self.buf
736 }
737}
738impl<'a> Iterator for IterableItemPort<'a> {
739 type Item = Result<ItemPort<'a>, ErrorContext>;
740 fn next(&mut self) -> Option<Self::Item> {
741 let mut pos;
742 let mut r#type;
743 loop {
744 pos = self.pos;
745 r#type = None;
746 if self.buf.len() == self.pos {
747 return None;
748 }
749 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
750 self.pos = self.buf.len();
751 break;
752 };
753 r#type = Some(header.r#type);
754 let res = match header.r#type {
755 1u16 => ItemPort::Port({
756 let res = Some(IterableAttrPort::with_loc(next, self.orig_loc));
757 let Some(val) = res else { break };
758 val
759 }),
760 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
761 n => continue,
762 };
763 return Some(Ok(res));
764 }
765 Some(Err(ErrorContext::new(
766 "ItemPort",
767 r#type.and_then(|t| ItemPort::attr_from_type(t)),
768 self.orig_loc,
769 self.buf.as_ptr().wrapping_add(pos) as usize,
770 )))
771 }
772}
773impl<'a> std::fmt::Debug for IterableItemPort<'_> {
774 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
775 let mut fmt = f.debug_struct("ItemPort");
776 for attr in self.clone() {
777 let attr = match attr {
778 Ok(a) => a,
779 Err(err) => {
780 fmt.finish()?;
781 f.write_str("Err(")?;
782 err.fmt(f)?;
783 return f.write_str(")");
784 }
785 };
786 match attr {
787 ItemPort::Port(val) => fmt.field("Port", &val),
788 };
789 }
790 fmt.finish()
791 }
792}
793impl IterableItemPort<'_> {
794 pub fn lookup_attr(
795 &self,
796 offset: usize,
797 missing_type: Option<u16>,
798 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
799 let mut stack = Vec::new();
800 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
801 if missing_type.is_some() && cur == offset {
802 stack.push(("ItemPort", offset));
803 return (
804 stack,
805 missing_type.and_then(|t| ItemPort::attr_from_type(t)),
806 );
807 }
808 if cur > offset || cur + self.buf.len() < offset {
809 return (stack, None);
810 }
811 let mut attrs = self.clone();
812 let mut last_off = cur + attrs.pos;
813 let mut missing = None;
814 while let Some(attr) = attrs.next() {
815 let Ok(attr) = attr else { break };
816 match attr {
817 ItemPort::Port(val) => {
818 (stack, missing) = val.lookup_attr(offset, missing_type);
819 if !stack.is_empty() {
820 break;
821 }
822 }
823 _ => {}
824 };
825 last_off = cur + attrs.pos;
826 }
827 if !stack.is_empty() {
828 stack.push(("ItemPort", cur));
829 }
830 (stack, missing)
831 }
832}
833#[derive(Clone)]
834pub enum AttrPort {
835 Ifindex(u32),
836 Changed(()),
837 Linkup(()),
838 Speed(u32),
839 Duplex(u8),
840 Removed(()),
841}
842impl<'a> IterableAttrPort<'a> {
843 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
844 let mut iter = self.clone();
845 iter.pos = 0;
846 for attr in iter {
847 if let Ok(AttrPort::Ifindex(val)) = attr {
848 return Ok(val);
849 }
850 }
851 Err(ErrorContext::new_missing(
852 "AttrPort",
853 "Ifindex",
854 self.orig_loc,
855 self.buf.as_ptr() as usize,
856 ))
857 }
858 pub fn get_changed(&self) -> Result<(), ErrorContext> {
859 let mut iter = self.clone();
860 iter.pos = 0;
861 for attr in iter {
862 if let Ok(AttrPort::Changed(val)) = attr {
863 return Ok(val);
864 }
865 }
866 Err(ErrorContext::new_missing(
867 "AttrPort",
868 "Changed",
869 self.orig_loc,
870 self.buf.as_ptr() as usize,
871 ))
872 }
873 pub fn get_linkup(&self) -> Result<(), ErrorContext> {
874 let mut iter = self.clone();
875 iter.pos = 0;
876 for attr in iter {
877 if let Ok(AttrPort::Linkup(val)) = attr {
878 return Ok(val);
879 }
880 }
881 Err(ErrorContext::new_missing(
882 "AttrPort",
883 "Linkup",
884 self.orig_loc,
885 self.buf.as_ptr() as usize,
886 ))
887 }
888 pub fn get_speed(&self) -> Result<u32, ErrorContext> {
889 let mut iter = self.clone();
890 iter.pos = 0;
891 for attr in iter {
892 if let Ok(AttrPort::Speed(val)) = attr {
893 return Ok(val);
894 }
895 }
896 Err(ErrorContext::new_missing(
897 "AttrPort",
898 "Speed",
899 self.orig_loc,
900 self.buf.as_ptr() as usize,
901 ))
902 }
903 pub fn get_duplex(&self) -> Result<u8, ErrorContext> {
904 let mut iter = self.clone();
905 iter.pos = 0;
906 for attr in iter {
907 if let Ok(AttrPort::Duplex(val)) = attr {
908 return Ok(val);
909 }
910 }
911 Err(ErrorContext::new_missing(
912 "AttrPort",
913 "Duplex",
914 self.orig_loc,
915 self.buf.as_ptr() as usize,
916 ))
917 }
918 pub fn get_removed(&self) -> Result<(), ErrorContext> {
919 let mut iter = self.clone();
920 iter.pos = 0;
921 for attr in iter {
922 if let Ok(AttrPort::Removed(val)) = attr {
923 return Ok(val);
924 }
925 }
926 Err(ErrorContext::new_missing(
927 "AttrPort",
928 "Removed",
929 self.orig_loc,
930 self.buf.as_ptr() as usize,
931 ))
932 }
933}
934impl AttrPort {
935 pub fn new<'a>(buf: &'a [u8]) -> IterableAttrPort<'a> {
936 IterableAttrPort::with_loc(buf, buf.as_ptr() as usize)
937 }
938 fn attr_from_type(r#type: u16) -> Option<&'static str> {
939 let res = match r#type {
940 0u16 => "Unspec",
941 1u16 => "Ifindex",
942 2u16 => "Changed",
943 3u16 => "Linkup",
944 4u16 => "Speed",
945 5u16 => "Duplex",
946 6u16 => "Removed",
947 _ => return None,
948 };
949 Some(res)
950 }
951}
952#[derive(Clone, Copy, Default)]
953pub struct IterableAttrPort<'a> {
954 buf: &'a [u8],
955 pos: usize,
956 orig_loc: usize,
957}
958impl<'a> IterableAttrPort<'a> {
959 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
960 Self {
961 buf,
962 pos: 0,
963 orig_loc,
964 }
965 }
966 pub fn get_buf(&self) -> &'a [u8] {
967 self.buf
968 }
969}
970impl<'a> Iterator for IterableAttrPort<'a> {
971 type Item = Result<AttrPort, ErrorContext>;
972 fn next(&mut self) -> Option<Self::Item> {
973 let mut pos;
974 let mut r#type;
975 loop {
976 pos = self.pos;
977 r#type = None;
978 if self.buf.len() == self.pos {
979 return None;
980 }
981 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
982 self.pos = self.buf.len();
983 break;
984 };
985 r#type = Some(header.r#type);
986 let res = match header.r#type {
987 1u16 => AttrPort::Ifindex({
988 let res = parse_u32(next);
989 let Some(val) = res else { break };
990 val
991 }),
992 2u16 => AttrPort::Changed(()),
993 3u16 => AttrPort::Linkup(()),
994 4u16 => AttrPort::Speed({
995 let res = parse_u32(next);
996 let Some(val) = res else { break };
997 val
998 }),
999 5u16 => AttrPort::Duplex({
1000 let res = parse_u8(next);
1001 let Some(val) = res else { break };
1002 val
1003 }),
1004 6u16 => AttrPort::Removed(()),
1005 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1006 n => continue,
1007 };
1008 return Some(Ok(res));
1009 }
1010 Some(Err(ErrorContext::new(
1011 "AttrPort",
1012 r#type.and_then(|t| AttrPort::attr_from_type(t)),
1013 self.orig_loc,
1014 self.buf.as_ptr().wrapping_add(pos) as usize,
1015 )))
1016 }
1017}
1018impl std::fmt::Debug for IterableAttrPort<'_> {
1019 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1020 let mut fmt = f.debug_struct("AttrPort");
1021 for attr in self.clone() {
1022 let attr = match attr {
1023 Ok(a) => a,
1024 Err(err) => {
1025 fmt.finish()?;
1026 f.write_str("Err(")?;
1027 err.fmt(f)?;
1028 return f.write_str(")");
1029 }
1030 };
1031 match attr {
1032 AttrPort::Ifindex(val) => fmt.field("Ifindex", &val),
1033 AttrPort::Changed(val) => fmt.field("Changed", &val),
1034 AttrPort::Linkup(val) => fmt.field("Linkup", &val),
1035 AttrPort::Speed(val) => fmt.field("Speed", &val),
1036 AttrPort::Duplex(val) => fmt.field("Duplex", &val),
1037 AttrPort::Removed(val) => fmt.field("Removed", &val),
1038 };
1039 }
1040 fmt.finish()
1041 }
1042}
1043impl IterableAttrPort<'_> {
1044 pub fn lookup_attr(
1045 &self,
1046 offset: usize,
1047 missing_type: Option<u16>,
1048 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1049 let mut stack = Vec::new();
1050 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1051 if missing_type.is_some() && cur == offset {
1052 stack.push(("AttrPort", offset));
1053 return (
1054 stack,
1055 missing_type.and_then(|t| AttrPort::attr_from_type(t)),
1056 );
1057 }
1058 if cur > offset || cur + self.buf.len() < offset {
1059 return (stack, None);
1060 }
1061 let mut attrs = self.clone();
1062 let mut last_off = cur + attrs.pos;
1063 while let Some(attr) = attrs.next() {
1064 let Ok(attr) = attr else { break };
1065 match attr {
1066 AttrPort::Ifindex(val) => {
1067 if last_off == offset {
1068 stack.push(("Ifindex", last_off));
1069 break;
1070 }
1071 }
1072 AttrPort::Changed(val) => {
1073 if last_off == offset {
1074 stack.push(("Changed", last_off));
1075 break;
1076 }
1077 }
1078 AttrPort::Linkup(val) => {
1079 if last_off == offset {
1080 stack.push(("Linkup", last_off));
1081 break;
1082 }
1083 }
1084 AttrPort::Speed(val) => {
1085 if last_off == offset {
1086 stack.push(("Speed", last_off));
1087 break;
1088 }
1089 }
1090 AttrPort::Duplex(val) => {
1091 if last_off == offset {
1092 stack.push(("Duplex", last_off));
1093 break;
1094 }
1095 }
1096 AttrPort::Removed(val) => {
1097 if last_off == offset {
1098 stack.push(("Removed", last_off));
1099 break;
1100 }
1101 }
1102 _ => {}
1103 };
1104 last_off = cur + attrs.pos;
1105 }
1106 if !stack.is_empty() {
1107 stack.push(("AttrPort", cur));
1108 }
1109 (stack, None)
1110 }
1111}
1112pub struct PushTeam<Prev: Rec> {
1113 pub(crate) prev: Option<Prev>,
1114 pub(crate) header_offset: Option<usize>,
1115}
1116impl<Prev: Rec> Rec for PushTeam<Prev> {
1117 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1118 self.prev.as_mut().unwrap().as_rec_mut()
1119 }
1120 fn as_rec(&self) -> &Vec<u8> {
1121 self.prev.as_ref().unwrap().as_rec()
1122 }
1123}
1124impl<Prev: Rec> PushTeam<Prev> {
1125 pub fn new(prev: Prev) -> Self {
1126 Self {
1127 prev: Some(prev),
1128 header_offset: None,
1129 }
1130 }
1131 pub fn end_nested(mut self) -> Prev {
1132 let mut prev = self.prev.take().unwrap();
1133 if let Some(header_offset) = &self.header_offset {
1134 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1135 }
1136 prev
1137 }
1138 pub fn push_team_ifindex(mut self, value: u32) -> Self {
1139 push_header(self.as_rec_mut(), 1u16, 4 as u16);
1140 self.as_rec_mut().extend(value.to_ne_bytes());
1141 self
1142 }
1143 pub fn nested_list_option(mut self) -> PushItemOption<Self> {
1144 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
1145 PushItemOption {
1146 prev: Some(self),
1147 header_offset: Some(header_offset),
1148 }
1149 }
1150 pub fn nested_list_port(mut self) -> PushItemPort<Self> {
1151 let header_offset = push_nested_header(self.as_rec_mut(), 3u16);
1152 PushItemPort {
1153 prev: Some(self),
1154 header_offset: Some(header_offset),
1155 }
1156 }
1157}
1158impl<Prev: Rec> Drop for PushTeam<Prev> {
1159 fn drop(&mut self) {
1160 if let Some(prev) = &mut self.prev {
1161 if let Some(header_offset) = &self.header_offset {
1162 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1163 }
1164 }
1165 }
1166}
1167pub struct PushItemOption<Prev: Rec> {
1168 pub(crate) prev: Option<Prev>,
1169 pub(crate) header_offset: Option<usize>,
1170}
1171impl<Prev: Rec> Rec for PushItemOption<Prev> {
1172 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1173 self.prev.as_mut().unwrap().as_rec_mut()
1174 }
1175 fn as_rec(&self) -> &Vec<u8> {
1176 self.prev.as_ref().unwrap().as_rec()
1177 }
1178}
1179impl<Prev: Rec> PushItemOption<Prev> {
1180 pub fn new(prev: Prev) -> Self {
1181 Self {
1182 prev: Some(prev),
1183 header_offset: None,
1184 }
1185 }
1186 pub fn end_nested(mut self) -> Prev {
1187 let mut prev = self.prev.take().unwrap();
1188 if let Some(header_offset) = &self.header_offset {
1189 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1190 }
1191 prev
1192 }
1193 pub fn nested_option(mut self) -> PushAttrOption<Self> {
1194 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
1195 PushAttrOption {
1196 prev: Some(self),
1197 header_offset: Some(header_offset),
1198 }
1199 }
1200}
1201impl<Prev: Rec> Drop for PushItemOption<Prev> {
1202 fn drop(&mut self) {
1203 if let Some(prev) = &mut self.prev {
1204 if let Some(header_offset) = &self.header_offset {
1205 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1206 }
1207 }
1208 }
1209}
1210pub struct PushAttrOption<Prev: Rec> {
1211 pub(crate) prev: Option<Prev>,
1212 pub(crate) header_offset: Option<usize>,
1213}
1214impl<Prev: Rec> Rec for PushAttrOption<Prev> {
1215 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1216 self.prev.as_mut().unwrap().as_rec_mut()
1217 }
1218 fn as_rec(&self) -> &Vec<u8> {
1219 self.prev.as_ref().unwrap().as_rec()
1220 }
1221}
1222impl<Prev: Rec> PushAttrOption<Prev> {
1223 pub fn new(prev: Prev) -> Self {
1224 Self {
1225 prev: Some(prev),
1226 header_offset: None,
1227 }
1228 }
1229 pub fn end_nested(mut self) -> Prev {
1230 let mut prev = self.prev.take().unwrap();
1231 if let Some(header_offset) = &self.header_offset {
1232 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1233 }
1234 prev
1235 }
1236 pub fn push_name(mut self, value: &CStr) -> Self {
1237 push_header(
1238 self.as_rec_mut(),
1239 1u16,
1240 value.to_bytes_with_nul().len() as u16,
1241 );
1242 self.as_rec_mut().extend(value.to_bytes_with_nul());
1243 self
1244 }
1245 pub fn push_name_bytes(mut self, value: &[u8]) -> Self {
1246 push_header(self.as_rec_mut(), 1u16, (value.len() + 1) as u16);
1247 self.as_rec_mut().extend(value);
1248 self.as_rec_mut().push(0);
1249 self
1250 }
1251 pub fn push_changed(mut self, value: ()) -> Self {
1252 push_header(self.as_rec_mut(), 2u16, 0 as u16);
1253 self
1254 }
1255 pub fn push_type(mut self, value: u8) -> Self {
1256 push_header(self.as_rec_mut(), 3u16, 1 as u16);
1257 self.as_rec_mut().extend(value.to_ne_bytes());
1258 self
1259 }
1260 pub fn push_data(mut self, value: &[u8]) -> Self {
1261 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
1262 self.as_rec_mut().extend(value);
1263 self
1264 }
1265 pub fn push_removed(mut self, value: ()) -> Self {
1266 push_header(self.as_rec_mut(), 5u16, 0 as u16);
1267 self
1268 }
1269 #[doc = "for per-port options\n"]
1270 pub fn push_port_ifindex(mut self, value: u32) -> Self {
1271 push_header(self.as_rec_mut(), 6u16, 4 as u16);
1272 self.as_rec_mut().extend(value.to_ne_bytes());
1273 self
1274 }
1275 #[doc = "for array options\n"]
1276 pub fn push_array_index(mut self, value: u32) -> Self {
1277 push_header(self.as_rec_mut(), 7u16, 4 as u16);
1278 self.as_rec_mut().extend(value.to_ne_bytes());
1279 self
1280 }
1281}
1282impl<Prev: Rec> Drop for PushAttrOption<Prev> {
1283 fn drop(&mut self) {
1284 if let Some(prev) = &mut self.prev {
1285 if let Some(header_offset) = &self.header_offset {
1286 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1287 }
1288 }
1289 }
1290}
1291pub struct PushItemPort<Prev: Rec> {
1292 pub(crate) prev: Option<Prev>,
1293 pub(crate) header_offset: Option<usize>,
1294}
1295impl<Prev: Rec> Rec for PushItemPort<Prev> {
1296 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1297 self.prev.as_mut().unwrap().as_rec_mut()
1298 }
1299 fn as_rec(&self) -> &Vec<u8> {
1300 self.prev.as_ref().unwrap().as_rec()
1301 }
1302}
1303impl<Prev: Rec> PushItemPort<Prev> {
1304 pub fn new(prev: Prev) -> Self {
1305 Self {
1306 prev: Some(prev),
1307 header_offset: None,
1308 }
1309 }
1310 pub fn end_nested(mut self) -> Prev {
1311 let mut prev = self.prev.take().unwrap();
1312 if let Some(header_offset) = &self.header_offset {
1313 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1314 }
1315 prev
1316 }
1317 pub fn nested_port(mut self) -> PushAttrPort<Self> {
1318 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
1319 PushAttrPort {
1320 prev: Some(self),
1321 header_offset: Some(header_offset),
1322 }
1323 }
1324}
1325impl<Prev: Rec> Drop for PushItemPort<Prev> {
1326 fn drop(&mut self) {
1327 if let Some(prev) = &mut self.prev {
1328 if let Some(header_offset) = &self.header_offset {
1329 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1330 }
1331 }
1332 }
1333}
1334pub struct PushAttrPort<Prev: Rec> {
1335 pub(crate) prev: Option<Prev>,
1336 pub(crate) header_offset: Option<usize>,
1337}
1338impl<Prev: Rec> Rec for PushAttrPort<Prev> {
1339 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
1340 self.prev.as_mut().unwrap().as_rec_mut()
1341 }
1342 fn as_rec(&self) -> &Vec<u8> {
1343 self.prev.as_ref().unwrap().as_rec()
1344 }
1345}
1346impl<Prev: Rec> PushAttrPort<Prev> {
1347 pub fn new(prev: Prev) -> Self {
1348 Self {
1349 prev: Some(prev),
1350 header_offset: None,
1351 }
1352 }
1353 pub fn end_nested(mut self) -> Prev {
1354 let mut prev = self.prev.take().unwrap();
1355 if let Some(header_offset) = &self.header_offset {
1356 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1357 }
1358 prev
1359 }
1360 pub fn push_ifindex(mut self, value: u32) -> Self {
1361 push_header(self.as_rec_mut(), 1u16, 4 as u16);
1362 self.as_rec_mut().extend(value.to_ne_bytes());
1363 self
1364 }
1365 pub fn push_changed(mut self, value: ()) -> Self {
1366 push_header(self.as_rec_mut(), 2u16, 0 as u16);
1367 self
1368 }
1369 pub fn push_linkup(mut self, value: ()) -> Self {
1370 push_header(self.as_rec_mut(), 3u16, 0 as u16);
1371 self
1372 }
1373 pub fn push_speed(mut self, value: u32) -> Self {
1374 push_header(self.as_rec_mut(), 4u16, 4 as u16);
1375 self.as_rec_mut().extend(value.to_ne_bytes());
1376 self
1377 }
1378 pub fn push_duplex(mut self, value: u8) -> Self {
1379 push_header(self.as_rec_mut(), 5u16, 1 as u16);
1380 self.as_rec_mut().extend(value.to_ne_bytes());
1381 self
1382 }
1383 pub fn push_removed(mut self, value: ()) -> Self {
1384 push_header(self.as_rec_mut(), 6u16, 0 as u16);
1385 self
1386 }
1387}
1388impl<Prev: Rec> Drop for PushAttrPort<Prev> {
1389 fn drop(&mut self) {
1390 if let Some(prev) = &mut self.prev {
1391 if let Some(header_offset) = &self.header_offset {
1392 finalize_nested_header(prev.as_rec_mut(), *header_offset);
1393 }
1394 }
1395 }
1396}
1397#[doc = "No operation\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n\n"]
1398#[derive(Debug)]
1399pub struct OpNoopDo<'r> {
1400 request: Request<'r>,
1401}
1402impl<'r> OpNoopDo<'r> {
1403 pub fn new(mut request: Request<'r>) -> Self {
1404 Self::write_header(request.buf_mut());
1405 Self { request: request }
1406 }
1407 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTeam<&'buf mut Vec<u8>> {
1408 Self::write_header(buf);
1409 PushTeam::new(buf)
1410 }
1411 pub fn encode(&mut self) -> PushTeam<&mut Vec<u8>> {
1412 PushTeam::new(self.request.buf_mut())
1413 }
1414 pub fn into_encoder(self) -> PushTeam<RequestBuf<'r>> {
1415 PushTeam::new(self.request.buf)
1416 }
1417 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTeam<'a> {
1418 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1419 IterableTeam::with_loc(attrs, buf.as_ptr() as usize)
1420 }
1421 fn write_header<Prev: Rec>(prev: &mut Prev) {
1422 let mut header = BuiltinNfgenmsg::new();
1423 header.cmd = 0u8;
1424 header.version = 1u8;
1425 prev.as_rec_mut().extend(header.as_slice());
1426 }
1427}
1428impl NetlinkRequest for OpNoopDo<'_> {
1429 fn protocol(&self) -> Protocol {
1430 Protocol::Generic("team".as_bytes())
1431 }
1432 fn flags(&self) -> u16 {
1433 self.request.flags
1434 }
1435 fn payload(&self) -> &[u8] {
1436 self.request.buf()
1437 }
1438 type ReplyType<'buf> = IterableTeam<'buf>;
1439 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1440 Self::decode_request(buf)
1441 }
1442 fn lookup(
1443 buf: &[u8],
1444 offset: usize,
1445 missing_type: Option<u16>,
1446 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1447 Self::decode_request(buf).lookup_attr(offset, missing_type)
1448 }
1449}
1450#[doc = "Set team options\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n- [.nested_list_option()](PushTeam::nested_list_option)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_option()](IterableTeam::get_list_option)\n\n"]
1451#[derive(Debug)]
1452pub struct OpOptionsSetDo<'r> {
1453 request: Request<'r>,
1454}
1455impl<'r> OpOptionsSetDo<'r> {
1456 pub fn new(mut request: Request<'r>) -> Self {
1457 Self::write_header(request.buf_mut());
1458 Self { request: request }
1459 }
1460 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTeam<&'buf mut Vec<u8>> {
1461 Self::write_header(buf);
1462 PushTeam::new(buf)
1463 }
1464 pub fn encode(&mut self) -> PushTeam<&mut Vec<u8>> {
1465 PushTeam::new(self.request.buf_mut())
1466 }
1467 pub fn into_encoder(self) -> PushTeam<RequestBuf<'r>> {
1468 PushTeam::new(self.request.buf)
1469 }
1470 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTeam<'a> {
1471 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1472 IterableTeam::with_loc(attrs, buf.as_ptr() as usize)
1473 }
1474 fn write_header<Prev: Rec>(prev: &mut Prev) {
1475 let mut header = BuiltinNfgenmsg::new();
1476 header.cmd = 1u8;
1477 header.version = 1u8;
1478 prev.as_rec_mut().extend(header.as_slice());
1479 }
1480}
1481impl NetlinkRequest for OpOptionsSetDo<'_> {
1482 fn protocol(&self) -> Protocol {
1483 Protocol::Generic("team".as_bytes())
1484 }
1485 fn flags(&self) -> u16 {
1486 self.request.flags
1487 }
1488 fn payload(&self) -> &[u8] {
1489 self.request.buf()
1490 }
1491 type ReplyType<'buf> = IterableTeam<'buf>;
1492 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1493 Self::decode_request(buf)
1494 }
1495 fn lookup(
1496 buf: &[u8],
1497 offset: usize,
1498 missing_type: Option<u16>,
1499 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1500 Self::decode_request(buf).lookup_attr(offset, missing_type)
1501 }
1502}
1503#[doc = "Get team options info\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_option()](IterableTeam::get_list_option)\n\n"]
1504#[derive(Debug)]
1505pub struct OpOptionsGetDo<'r> {
1506 request: Request<'r>,
1507}
1508impl<'r> OpOptionsGetDo<'r> {
1509 pub fn new(mut request: Request<'r>) -> Self {
1510 Self::write_header(request.buf_mut());
1511 Self { request: request }
1512 }
1513 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTeam<&'buf mut Vec<u8>> {
1514 Self::write_header(buf);
1515 PushTeam::new(buf)
1516 }
1517 pub fn encode(&mut self) -> PushTeam<&mut Vec<u8>> {
1518 PushTeam::new(self.request.buf_mut())
1519 }
1520 pub fn into_encoder(self) -> PushTeam<RequestBuf<'r>> {
1521 PushTeam::new(self.request.buf)
1522 }
1523 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTeam<'a> {
1524 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1525 IterableTeam::with_loc(attrs, buf.as_ptr() as usize)
1526 }
1527 fn write_header<Prev: Rec>(prev: &mut Prev) {
1528 let mut header = BuiltinNfgenmsg::new();
1529 header.cmd = 2u8;
1530 header.version = 1u8;
1531 prev.as_rec_mut().extend(header.as_slice());
1532 }
1533}
1534impl NetlinkRequest for OpOptionsGetDo<'_> {
1535 fn protocol(&self) -> Protocol {
1536 Protocol::Generic("team".as_bytes())
1537 }
1538 fn flags(&self) -> u16 {
1539 self.request.flags
1540 }
1541 fn payload(&self) -> &[u8] {
1542 self.request.buf()
1543 }
1544 type ReplyType<'buf> = IterableTeam<'buf>;
1545 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1546 Self::decode_request(buf)
1547 }
1548 fn lookup(
1549 buf: &[u8],
1550 offset: usize,
1551 missing_type: Option<u16>,
1552 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1553 Self::decode_request(buf).lookup_attr(offset, missing_type)
1554 }
1555}
1556#[doc = "Get team ports info\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_port()](IterableTeam::get_list_port)\n\n"]
1557#[derive(Debug)]
1558pub struct OpPortListGetDo<'r> {
1559 request: Request<'r>,
1560}
1561impl<'r> OpPortListGetDo<'r> {
1562 pub fn new(mut request: Request<'r>) -> Self {
1563 Self::write_header(request.buf_mut());
1564 Self { request: request }
1565 }
1566 pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTeam<&'buf mut Vec<u8>> {
1567 Self::write_header(buf);
1568 PushTeam::new(buf)
1569 }
1570 pub fn encode(&mut self) -> PushTeam<&mut Vec<u8>> {
1571 PushTeam::new(self.request.buf_mut())
1572 }
1573 pub fn into_encoder(self) -> PushTeam<RequestBuf<'r>> {
1574 PushTeam::new(self.request.buf)
1575 }
1576 pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTeam<'a> {
1577 let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1578 IterableTeam::with_loc(attrs, buf.as_ptr() as usize)
1579 }
1580 fn write_header<Prev: Rec>(prev: &mut Prev) {
1581 let mut header = BuiltinNfgenmsg::new();
1582 header.cmd = 3u8;
1583 header.version = 1u8;
1584 prev.as_rec_mut().extend(header.as_slice());
1585 }
1586}
1587impl NetlinkRequest for OpPortListGetDo<'_> {
1588 fn protocol(&self) -> Protocol {
1589 Protocol::Generic("team".as_bytes())
1590 }
1591 fn flags(&self) -> u16 {
1592 self.request.flags
1593 }
1594 fn payload(&self) -> &[u8] {
1595 self.request.buf()
1596 }
1597 type ReplyType<'buf> = IterableTeam<'buf>;
1598 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1599 Self::decode_request(buf)
1600 }
1601 fn lookup(
1602 buf: &[u8],
1603 offset: usize,
1604 missing_type: Option<u16>,
1605 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1606 Self::decode_request(buf).lookup_attr(offset, missing_type)
1607 }
1608}
1609use crate::traits::LookupFn;
1610use crate::utils::RequestBuf;
1611#[derive(Debug)]
1612pub struct Request<'buf> {
1613 buf: RequestBuf<'buf>,
1614 flags: u16,
1615 writeback: Option<&'buf mut Option<RequestInfo>>,
1616}
1617#[allow(unused)]
1618#[derive(Debug, Clone)]
1619pub struct RequestInfo {
1620 protocol: Protocol,
1621 flags: u16,
1622 name: &'static str,
1623 lookup: LookupFn,
1624}
1625impl Request<'static> {
1626 pub fn new() -> Self {
1627 Self::new_from_buf(Vec::new())
1628 }
1629 pub fn new_from_buf(buf: Vec<u8>) -> Self {
1630 Self {
1631 flags: 0,
1632 buf: RequestBuf::Own(buf),
1633 writeback: None,
1634 }
1635 }
1636 pub fn into_buf(self) -> Vec<u8> {
1637 match self.buf {
1638 RequestBuf::Own(buf) => buf,
1639 _ => unreachable!(),
1640 }
1641 }
1642}
1643impl<'buf> Request<'buf> {
1644 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1645 buf.clear();
1646 Self::new_extend(buf)
1647 }
1648 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1649 Self {
1650 flags: 0,
1651 buf: RequestBuf::Ref(buf),
1652 writeback: None,
1653 }
1654 }
1655 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1656 let Some(writeback) = &mut self.writeback else {
1657 return;
1658 };
1659 **writeback = Some(RequestInfo {
1660 protocol,
1661 flags: self.flags,
1662 name,
1663 lookup,
1664 })
1665 }
1666 pub fn buf(&self) -> &Vec<u8> {
1667 self.buf.buf()
1668 }
1669 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1670 self.buf.buf_mut()
1671 }
1672 #[doc = "Set `NLM_F_CREATE` flag"]
1673 pub fn set_create(mut self) -> Self {
1674 self.flags |= consts::NLM_F_CREATE as u16;
1675 self
1676 }
1677 #[doc = "Set `NLM_F_EXCL` flag"]
1678 pub fn set_excl(mut self) -> Self {
1679 self.flags |= consts::NLM_F_EXCL as u16;
1680 self
1681 }
1682 #[doc = "Set `NLM_F_REPLACE` flag"]
1683 pub fn set_replace(mut self) -> Self {
1684 self.flags |= consts::NLM_F_REPLACE as u16;
1685 self
1686 }
1687 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1688 pub fn set_change(self) -> Self {
1689 self.set_create().set_replace()
1690 }
1691 #[doc = "Set `NLM_F_APPEND` flag"]
1692 pub fn set_append(mut self) -> Self {
1693 self.flags |= consts::NLM_F_APPEND as u16;
1694 self
1695 }
1696 #[doc = "Set `self.flags |= flags`"]
1697 pub fn set_flags(mut self, flags: u16) -> Self {
1698 self.flags |= flags;
1699 self
1700 }
1701 #[doc = "Set `self.flags ^= self.flags & flags`"]
1702 pub fn unset_flags(mut self, flags: u16) -> Self {
1703 self.flags ^= self.flags & flags;
1704 self
1705 }
1706 #[doc = "No operation\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n\n"]
1707 pub fn op_noop_do(self) -> OpNoopDo<'buf> {
1708 let mut res = OpNoopDo::new(self);
1709 res.request
1710 .do_writeback(res.protocol(), "op-noop-do", OpNoopDo::lookup);
1711 res
1712 }
1713 #[doc = "Set team options\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n- [.nested_list_option()](PushTeam::nested_list_option)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_option()](IterableTeam::get_list_option)\n\n"]
1714 pub fn op_options_set_do(self) -> OpOptionsSetDo<'buf> {
1715 let mut res = OpOptionsSetDo::new(self);
1716 res.request
1717 .do_writeback(res.protocol(), "op-options-set-do", OpOptionsSetDo::lookup);
1718 res
1719 }
1720 #[doc = "Get team options info\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_option()](IterableTeam::get_list_option)\n\n"]
1721 pub fn op_options_get_do(self) -> OpOptionsGetDo<'buf> {
1722 let mut res = OpOptionsGetDo::new(self);
1723 res.request
1724 .do_writeback(res.protocol(), "op-options-get-do", OpOptionsGetDo::lookup);
1725 res
1726 }
1727 #[doc = "Get team ports info\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_team_ifindex()](PushTeam::push_team_ifindex)\n\nReply attributes:\n- [.get_team_ifindex()](IterableTeam::get_team_ifindex)\n- [.get_list_port()](IterableTeam::get_list_port)\n\n"]
1728 pub fn op_port_list_get_do(self) -> OpPortListGetDo<'buf> {
1729 let mut res = OpPortListGetDo::new(self);
1730 res.request.do_writeback(
1731 res.protocol(),
1732 "op-port-list-get-do",
1733 OpPortListGetDo::lookup,
1734 );
1735 res
1736 }
1737}
1738#[cfg(test)]
1739mod generated_tests {
1740 use super::*;
1741 #[test]
1742 fn tests() {
1743 let _ = IterableTeam::get_list_option;
1744 let _ = IterableTeam::get_list_port;
1745 let _ = IterableTeam::get_team_ifindex;
1746 let _ = PushTeam::<&mut Vec<u8>>::nested_list_option;
1747 let _ = PushTeam::<&mut Vec<u8>>::push_team_ifindex;
1748 }
1749}