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