1#![doc = "netdev configuration over generic netlink."]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{PushBuiltinBitfield32, PushBuiltinNfgenmsg, PushDummy, PushNlmsghdr};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &CStr = c"netdev";
17#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
18#[derive(Debug, Clone, Copy)]
19pub enum XdpAct {
20 #[doc = "XDP features set supported by all drivers (XDP_ABORTED, XDP_DROP, XDP_PASS, XDP_TX)"]
21 Basic = 1 << 0,
22 #[doc = "The netdev supports XDP_REDIRECT"]
23 Redirect = 1 << 1,
24 #[doc = "This feature informs if netdev implements ndo_xdp_xmit callback."]
25 NdoXmit = 1 << 2,
26 #[doc = "This feature informs if netdev supports AF_XDP in zero copy mode."]
27 XskZerocopy = 1 << 3,
28 #[doc = "This feature informs if netdev supports XDP hw offloading."]
29 HwOffload = 1 << 4,
30 #[doc = "This feature informs if netdev implements non-linear XDP buffer support in the driver napi callback."]
31 RxSg = 1 << 5,
32 #[doc = "This feature informs if netdev implements non-linear XDP buffer support in ndo_xdp_xmit callback."]
33 NdoXmitSg = 1 << 6,
34}
35impl XdpAct {
36 pub fn from_value(value: u64) -> Option<Self> {
37 Some(match value {
38 n if n == 1 << 0 => Self::Basic,
39 n if n == 1 << 1 => Self::Redirect,
40 n if n == 1 << 2 => Self::NdoXmit,
41 n if n == 1 << 3 => Self::XskZerocopy,
42 n if n == 1 << 4 => Self::HwOffload,
43 n if n == 1 << 5 => Self::RxSg,
44 n if n == 1 << 6 => Self::NdoXmitSg,
45 _ => return None,
46 })
47 }
48}
49#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
50#[derive(Debug, Clone, Copy)]
51pub enum XdpRxMetadata {
52 #[doc = "Device is capable of exposing receive HW timestamp via\nbpf_xdp_metadata_rx_timestamp().\n"]
53 Timestamp = 1 << 0,
54 #[doc = "Device is capable of exposing receive packet hash via\nbpf_xdp_metadata_rx_hash().\n"]
55 Hash = 1 << 1,
56 #[doc = "Device is capable of exposing receive packet VLAN tag via\nbpf_xdp_metadata_rx_vlan_tag().\n"]
57 VlanTag = 1 << 2,
58}
59impl XdpRxMetadata {
60 pub fn from_value(value: u64) -> Option<Self> {
61 Some(match value {
62 n if n == 1 << 0 => Self::Timestamp,
63 n if n == 1 << 1 => Self::Hash,
64 n if n == 1 << 2 => Self::VlanTag,
65 _ => return None,
66 })
67 }
68}
69#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
70#[derive(Debug, Clone, Copy)]
71pub enum XskFlags {
72 #[doc = "HW timestamping egress packets is supported by the driver."]
73 TxTimestamp = 1 << 0,
74 #[doc = "L3 checksum HW offload is supported by the driver."]
75 TxChecksum = 1 << 1,
76 #[doc = "Launch time HW offload is supported by the driver."]
77 TxLaunchTimeFifo = 1 << 2,
78}
79impl XskFlags {
80 pub fn from_value(value: u64) -> Option<Self> {
81 Some(match value {
82 n if n == 1 << 0 => Self::TxTimestamp,
83 n if n == 1 << 1 => Self::TxChecksum,
84 n if n == 1 << 2 => Self::TxLaunchTimeFifo,
85 _ => return None,
86 })
87 }
88}
89#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
90#[derive(Debug, Clone, Copy)]
91pub enum QueueType {
92 Rx = 0,
93 Tx = 1,
94}
95impl QueueType {
96 pub fn from_value(value: u64) -> Option<Self> {
97 Some(match value {
98 0 => Self::Rx,
99 1 => Self::Tx,
100 _ => return None,
101 })
102 }
103}
104#[doc = "Flags - defines an integer enumeration, with values for each entry occupying a bit, starting from bit 0, (e.g. 1, 2, 4, 8)"]
105#[derive(Debug, Clone, Copy)]
106pub enum QstatsScope {
107 Queue = 1 << 0,
108}
109impl QstatsScope {
110 pub fn from_value(value: u64) -> Option<Self> {
111 Some(match value {
112 n if n == 1 << 0 => Self::Queue,
113 _ => return None,
114 })
115 }
116}
117#[doc = "Enum - defines an integer enumeration, with values for each entry incrementing by 1, (e.g. 0, 1, 2, 3)"]
118#[derive(Debug, Clone, Copy)]
119pub enum NapiThreaded {
120 Disabled = 0,
121 Enabled = 1,
122 BusyPoll = 2,
123}
124impl NapiThreaded {
125 pub fn from_value(value: u64) -> Option<Self> {
126 Some(match value {
127 0 => Self::Disabled,
128 1 => Self::Enabled,
129 2 => Self::BusyPoll,
130 _ => return None,
131 })
132 }
133}
134#[derive(Clone)]
135pub enum Dev<'a> {
136 #[doc = "netdev ifindex"]
137 Ifindex(u32),
138 Pad(&'a [u8]),
139 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
140 XdpFeatures(u64),
141 #[doc = "max fragment count supported by ZC driver"]
142 XdpZcMaxSegs(u32),
143 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
144 XdpRxMetadataFeatures(u64),
145 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
146 XskFeatures(u64),
147}
148impl<'a> IterableDev<'a> {
149 #[doc = "netdev ifindex"]
150 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
151 let mut iter = self.clone();
152 iter.pos = 0;
153 for attr in iter {
154 if let Dev::Ifindex(val) = attr? {
155 return Ok(val);
156 }
157 }
158 Err(ErrorContext::new_missing(
159 "Dev",
160 "Ifindex",
161 self.orig_loc,
162 self.buf.as_ptr() as usize,
163 ))
164 }
165 pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
166 let mut iter = self.clone();
167 iter.pos = 0;
168 for attr in iter {
169 if let Dev::Pad(val) = attr? {
170 return Ok(val);
171 }
172 }
173 Err(ErrorContext::new_missing(
174 "Dev",
175 "Pad",
176 self.orig_loc,
177 self.buf.as_ptr() as usize,
178 ))
179 }
180 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
181 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
182 let mut iter = self.clone();
183 iter.pos = 0;
184 for attr in iter {
185 if let Dev::XdpFeatures(val) = attr? {
186 return Ok(val);
187 }
188 }
189 Err(ErrorContext::new_missing(
190 "Dev",
191 "XdpFeatures",
192 self.orig_loc,
193 self.buf.as_ptr() as usize,
194 ))
195 }
196 #[doc = "max fragment count supported by ZC driver"]
197 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
198 let mut iter = self.clone();
199 iter.pos = 0;
200 for attr in iter {
201 if let Dev::XdpZcMaxSegs(val) = attr? {
202 return Ok(val);
203 }
204 }
205 Err(ErrorContext::new_missing(
206 "Dev",
207 "XdpZcMaxSegs",
208 self.orig_loc,
209 self.buf.as_ptr() as usize,
210 ))
211 }
212 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
213 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
214 let mut iter = self.clone();
215 iter.pos = 0;
216 for attr in iter {
217 if let Dev::XdpRxMetadataFeatures(val) = attr? {
218 return Ok(val);
219 }
220 }
221 Err(ErrorContext::new_missing(
222 "Dev",
223 "XdpRxMetadataFeatures",
224 self.orig_loc,
225 self.buf.as_ptr() as usize,
226 ))
227 }
228 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
229 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
230 let mut iter = self.clone();
231 iter.pos = 0;
232 for attr in iter {
233 if let Dev::XskFeatures(val) = attr? {
234 return Ok(val);
235 }
236 }
237 Err(ErrorContext::new_missing(
238 "Dev",
239 "XskFeatures",
240 self.orig_loc,
241 self.buf.as_ptr() as usize,
242 ))
243 }
244}
245impl Dev<'_> {
246 pub fn new<'a>(buf: &'a [u8]) -> IterableDev<'a> {
247 IterableDev::with_loc(buf, buf.as_ptr() as usize)
248 }
249 fn attr_from_type(r#type: u16) -> Option<&'static str> {
250 let res = match r#type {
251 1u16 => "Ifindex",
252 2u16 => "Pad",
253 3u16 => "XdpFeatures",
254 4u16 => "XdpZcMaxSegs",
255 5u16 => "XdpRxMetadataFeatures",
256 6u16 => "XskFeatures",
257 _ => return None,
258 };
259 Some(res)
260 }
261}
262#[derive(Clone, Copy, Default)]
263pub struct IterableDev<'a> {
264 buf: &'a [u8],
265 pos: usize,
266 orig_loc: usize,
267}
268impl<'a> IterableDev<'a> {
269 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
270 Self {
271 buf,
272 pos: 0,
273 orig_loc,
274 }
275 }
276 pub fn get_buf(&self) -> &'a [u8] {
277 self.buf
278 }
279}
280impl<'a> Iterator for IterableDev<'a> {
281 type Item = Result<Dev<'a>, ErrorContext>;
282 fn next(&mut self) -> Option<Self::Item> {
283 let pos = self.pos;
284 let mut r#type;
285 loop {
286 r#type = None;
287 if self.buf.len() == self.pos {
288 return None;
289 }
290 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
291 break;
292 };
293 r#type = Some(header.r#type);
294 let res = match header.r#type {
295 1u16 => Dev::Ifindex({
296 let res = parse_u32(next);
297 let Some(val) = res else { break };
298 val
299 }),
300 2u16 => Dev::Pad({
301 let res = Some(next);
302 let Some(val) = res else { break };
303 val
304 }),
305 3u16 => Dev::XdpFeatures({
306 let res = parse_u64(next);
307 let Some(val) = res else { break };
308 val
309 }),
310 4u16 => Dev::XdpZcMaxSegs({
311 let res = parse_u32(next);
312 let Some(val) = res else { break };
313 val
314 }),
315 5u16 => Dev::XdpRxMetadataFeatures({
316 let res = parse_u64(next);
317 let Some(val) = res else { break };
318 val
319 }),
320 6u16 => Dev::XskFeatures({
321 let res = parse_u64(next);
322 let Some(val) = res else { break };
323 val
324 }),
325 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
326 n => continue,
327 };
328 return Some(Ok(res));
329 }
330 Some(Err(ErrorContext::new(
331 "Dev",
332 r#type.and_then(|t| Dev::attr_from_type(t)),
333 self.orig_loc,
334 self.buf.as_ptr().wrapping_add(pos) as usize,
335 )))
336 }
337}
338impl<'a> std::fmt::Debug for IterableDev<'_> {
339 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340 let mut fmt = f.debug_struct("Dev");
341 for attr in self.clone() {
342 let attr = match attr {
343 Ok(a) => a,
344 Err(err) => {
345 fmt.finish()?;
346 f.write_str("Err(")?;
347 err.fmt(f)?;
348 return f.write_str(")");
349 }
350 };
351 match attr {
352 Dev::Ifindex(val) => fmt.field("Ifindex", &val),
353 Dev::Pad(val) => fmt.field("Pad", &val),
354 Dev::XdpFeatures(val) => {
355 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
356 }
357 Dev::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
358 Dev::XdpRxMetadataFeatures(val) => fmt.field(
359 "XdpRxMetadataFeatures",
360 &FormatFlags(val.into(), XdpRxMetadata::from_value),
361 ),
362 Dev::XskFeatures(val) => fmt.field(
363 "XskFeatures",
364 &FormatFlags(val.into(), XskFlags::from_value),
365 ),
366 };
367 }
368 fmt.finish()
369 }
370}
371impl IterableDev<'_> {
372 pub fn lookup_attr(
373 &self,
374 offset: usize,
375 missing_type: Option<u16>,
376 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
377 let mut stack = Vec::new();
378 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
379 if cur == offset {
380 stack.push(("Dev", offset));
381 return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
382 }
383 if cur > offset || cur + self.buf.len() < offset {
384 return (stack, None);
385 }
386 let mut attrs = self.clone();
387 let mut last_off = cur + attrs.pos;
388 while let Some(attr) = attrs.next() {
389 let Ok(attr) = attr else { break };
390 match attr {
391 Dev::Ifindex(val) => {
392 if last_off == offset {
393 stack.push(("Ifindex", last_off));
394 break;
395 }
396 }
397 Dev::Pad(val) => {
398 if last_off == offset {
399 stack.push(("Pad", last_off));
400 break;
401 }
402 }
403 Dev::XdpFeatures(val) => {
404 if last_off == offset {
405 stack.push(("XdpFeatures", last_off));
406 break;
407 }
408 }
409 Dev::XdpZcMaxSegs(val) => {
410 if last_off == offset {
411 stack.push(("XdpZcMaxSegs", last_off));
412 break;
413 }
414 }
415 Dev::XdpRxMetadataFeatures(val) => {
416 if last_off == offset {
417 stack.push(("XdpRxMetadataFeatures", last_off));
418 break;
419 }
420 }
421 Dev::XskFeatures(val) => {
422 if last_off == offset {
423 stack.push(("XskFeatures", last_off));
424 break;
425 }
426 }
427 _ => {}
428 };
429 last_off = cur + attrs.pos;
430 }
431 if !stack.is_empty() {
432 stack.push(("Dev", cur));
433 }
434 (stack, None)
435 }
436}
437#[derive(Clone)]
438pub enum IoUringProviderInfo {}
439impl<'a> IterableIoUringProviderInfo<'a> {}
440impl IoUringProviderInfo {
441 pub fn new<'a>(buf: &'a [u8]) -> IterableIoUringProviderInfo<'a> {
442 IterableIoUringProviderInfo::with_loc(buf, buf.as_ptr() as usize)
443 }
444 fn attr_from_type(r#type: u16) -> Option<&'static str> {
445 None
446 }
447}
448#[derive(Clone, Copy, Default)]
449pub struct IterableIoUringProviderInfo<'a> {
450 buf: &'a [u8],
451 pos: usize,
452 orig_loc: usize,
453}
454impl<'a> IterableIoUringProviderInfo<'a> {
455 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
456 Self {
457 buf,
458 pos: 0,
459 orig_loc,
460 }
461 }
462 pub fn get_buf(&self) -> &'a [u8] {
463 self.buf
464 }
465}
466impl<'a> Iterator for IterableIoUringProviderInfo<'a> {
467 type Item = Result<IoUringProviderInfo, ErrorContext>;
468 fn next(&mut self) -> Option<Self::Item> {
469 let pos = self.pos;
470 let mut r#type;
471 loop {
472 r#type = None;
473 if self.buf.len() == self.pos {
474 return None;
475 }
476 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
477 break;
478 };
479 r#type = Some(header.r#type);
480 let res = match header.r#type {
481 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
482 n => continue,
483 };
484 return Some(Ok(res));
485 }
486 Some(Err(ErrorContext::new(
487 "IoUringProviderInfo",
488 r#type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
489 self.orig_loc,
490 self.buf.as_ptr().wrapping_add(pos) as usize,
491 )))
492 }
493}
494impl std::fmt::Debug for IterableIoUringProviderInfo<'_> {
495 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496 let mut fmt = f.debug_struct("IoUringProviderInfo");
497 for attr in self.clone() {
498 let attr = match attr {
499 Ok(a) => a,
500 Err(err) => {
501 fmt.finish()?;
502 f.write_str("Err(")?;
503 err.fmt(f)?;
504 return f.write_str(")");
505 }
506 };
507 match attr {};
508 }
509 fmt.finish()
510 }
511}
512impl IterableIoUringProviderInfo<'_> {
513 pub fn lookup_attr(
514 &self,
515 offset: usize,
516 missing_type: Option<u16>,
517 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
518 let mut stack = Vec::new();
519 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
520 if cur == offset {
521 stack.push(("IoUringProviderInfo", offset));
522 return (
523 stack,
524 missing_type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
525 );
526 }
527 (stack, None)
528 }
529}
530#[derive(Clone)]
531pub enum PagePool<'a> {
532 #[doc = "Unique ID of a Page Pool instance."]
533 Id(u32),
534 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
535 Ifindex(u32),
536 #[doc = "Id of NAPI using this Page Pool instance."]
537 NapiId(u32),
538 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
539 Inflight(u32),
540 #[doc = "Amount of memory held by inflight pages.\n"]
541 InflightMem(u32),
542 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
543 DetachTime(u32),
544 #[doc = "ID of the dmabuf this page-pool is attached to."]
545 Dmabuf(u32),
546 #[doc = "io-uring memory provider information."]
547 IoUring(IterableIoUringProviderInfo<'a>),
548}
549impl<'a> IterablePagePool<'a> {
550 #[doc = "Unique ID of a Page Pool instance."]
551 pub fn get_id(&self) -> Result<u32, ErrorContext> {
552 let mut iter = self.clone();
553 iter.pos = 0;
554 for attr in iter {
555 if let PagePool::Id(val) = attr? {
556 return Ok(val);
557 }
558 }
559 Err(ErrorContext::new_missing(
560 "PagePool",
561 "Id",
562 self.orig_loc,
563 self.buf.as_ptr() as usize,
564 ))
565 }
566 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
567 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
568 let mut iter = self.clone();
569 iter.pos = 0;
570 for attr in iter {
571 if let PagePool::Ifindex(val) = attr? {
572 return Ok(val);
573 }
574 }
575 Err(ErrorContext::new_missing(
576 "PagePool",
577 "Ifindex",
578 self.orig_loc,
579 self.buf.as_ptr() as usize,
580 ))
581 }
582 #[doc = "Id of NAPI using this Page Pool instance."]
583 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
584 let mut iter = self.clone();
585 iter.pos = 0;
586 for attr in iter {
587 if let PagePool::NapiId(val) = attr? {
588 return Ok(val);
589 }
590 }
591 Err(ErrorContext::new_missing(
592 "PagePool",
593 "NapiId",
594 self.orig_loc,
595 self.buf.as_ptr() as usize,
596 ))
597 }
598 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
599 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
600 let mut iter = self.clone();
601 iter.pos = 0;
602 for attr in iter {
603 if let PagePool::Inflight(val) = attr? {
604 return Ok(val);
605 }
606 }
607 Err(ErrorContext::new_missing(
608 "PagePool",
609 "Inflight",
610 self.orig_loc,
611 self.buf.as_ptr() as usize,
612 ))
613 }
614 #[doc = "Amount of memory held by inflight pages.\n"]
615 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
616 let mut iter = self.clone();
617 iter.pos = 0;
618 for attr in iter {
619 if let PagePool::InflightMem(val) = attr? {
620 return Ok(val);
621 }
622 }
623 Err(ErrorContext::new_missing(
624 "PagePool",
625 "InflightMem",
626 self.orig_loc,
627 self.buf.as_ptr() as usize,
628 ))
629 }
630 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
631 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
632 let mut iter = self.clone();
633 iter.pos = 0;
634 for attr in iter {
635 if let PagePool::DetachTime(val) = attr? {
636 return Ok(val);
637 }
638 }
639 Err(ErrorContext::new_missing(
640 "PagePool",
641 "DetachTime",
642 self.orig_loc,
643 self.buf.as_ptr() as usize,
644 ))
645 }
646 #[doc = "ID of the dmabuf this page-pool is attached to."]
647 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
648 let mut iter = self.clone();
649 iter.pos = 0;
650 for attr in iter {
651 if let PagePool::Dmabuf(val) = attr? {
652 return Ok(val);
653 }
654 }
655 Err(ErrorContext::new_missing(
656 "PagePool",
657 "Dmabuf",
658 self.orig_loc,
659 self.buf.as_ptr() as usize,
660 ))
661 }
662 #[doc = "io-uring memory provider information."]
663 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
664 let mut iter = self.clone();
665 iter.pos = 0;
666 for attr in iter {
667 if let PagePool::IoUring(val) = attr? {
668 return Ok(val);
669 }
670 }
671 Err(ErrorContext::new_missing(
672 "PagePool",
673 "IoUring",
674 self.orig_loc,
675 self.buf.as_ptr() as usize,
676 ))
677 }
678}
679impl PagePool<'_> {
680 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
681 IterablePagePool::with_loc(buf, buf.as_ptr() as usize)
682 }
683 fn attr_from_type(r#type: u16) -> Option<&'static str> {
684 let res = match r#type {
685 1u16 => "Id",
686 2u16 => "Ifindex",
687 3u16 => "NapiId",
688 4u16 => "Inflight",
689 5u16 => "InflightMem",
690 6u16 => "DetachTime",
691 7u16 => "Dmabuf",
692 8u16 => "IoUring",
693 _ => return None,
694 };
695 Some(res)
696 }
697}
698#[derive(Clone, Copy, Default)]
699pub struct IterablePagePool<'a> {
700 buf: &'a [u8],
701 pos: usize,
702 orig_loc: usize,
703}
704impl<'a> IterablePagePool<'a> {
705 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
706 Self {
707 buf,
708 pos: 0,
709 orig_loc,
710 }
711 }
712 pub fn get_buf(&self) -> &'a [u8] {
713 self.buf
714 }
715}
716impl<'a> Iterator for IterablePagePool<'a> {
717 type Item = Result<PagePool<'a>, ErrorContext>;
718 fn next(&mut self) -> Option<Self::Item> {
719 let pos = self.pos;
720 let mut r#type;
721 loop {
722 r#type = None;
723 if self.buf.len() == self.pos {
724 return None;
725 }
726 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
727 break;
728 };
729 r#type = Some(header.r#type);
730 let res = match header.r#type {
731 1u16 => PagePool::Id({
732 let res = parse_u32(next);
733 let Some(val) = res else { break };
734 val
735 }),
736 2u16 => PagePool::Ifindex({
737 let res = parse_u32(next);
738 let Some(val) = res else { break };
739 val
740 }),
741 3u16 => PagePool::NapiId({
742 let res = parse_u32(next);
743 let Some(val) = res else { break };
744 val
745 }),
746 4u16 => PagePool::Inflight({
747 let res = parse_u32(next);
748 let Some(val) = res else { break };
749 val
750 }),
751 5u16 => PagePool::InflightMem({
752 let res = parse_u32(next);
753 let Some(val) = res else { break };
754 val
755 }),
756 6u16 => PagePool::DetachTime({
757 let res = parse_u32(next);
758 let Some(val) = res else { break };
759 val
760 }),
761 7u16 => PagePool::Dmabuf({
762 let res = parse_u32(next);
763 let Some(val) = res else { break };
764 val
765 }),
766 8u16 => PagePool::IoUring({
767 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
768 let Some(val) = res else { break };
769 val
770 }),
771 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
772 n => continue,
773 };
774 return Some(Ok(res));
775 }
776 Some(Err(ErrorContext::new(
777 "PagePool",
778 r#type.and_then(|t| PagePool::attr_from_type(t)),
779 self.orig_loc,
780 self.buf.as_ptr().wrapping_add(pos) as usize,
781 )))
782 }
783}
784impl<'a> std::fmt::Debug for IterablePagePool<'_> {
785 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
786 let mut fmt = f.debug_struct("PagePool");
787 for attr in self.clone() {
788 let attr = match attr {
789 Ok(a) => a,
790 Err(err) => {
791 fmt.finish()?;
792 f.write_str("Err(")?;
793 err.fmt(f)?;
794 return f.write_str(")");
795 }
796 };
797 match attr {
798 PagePool::Id(val) => fmt.field("Id", &val),
799 PagePool::Ifindex(val) => fmt.field("Ifindex", &val),
800 PagePool::NapiId(val) => fmt.field("NapiId", &val),
801 PagePool::Inflight(val) => fmt.field("Inflight", &val),
802 PagePool::InflightMem(val) => fmt.field("InflightMem", &val),
803 PagePool::DetachTime(val) => fmt.field("DetachTime", &val),
804 PagePool::Dmabuf(val) => fmt.field("Dmabuf", &val),
805 PagePool::IoUring(val) => fmt.field("IoUring", &val),
806 };
807 }
808 fmt.finish()
809 }
810}
811impl IterablePagePool<'_> {
812 pub fn lookup_attr(
813 &self,
814 offset: usize,
815 missing_type: Option<u16>,
816 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
817 let mut stack = Vec::new();
818 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
819 if cur == offset {
820 stack.push(("PagePool", offset));
821 return (
822 stack,
823 missing_type.and_then(|t| PagePool::attr_from_type(t)),
824 );
825 }
826 if cur > offset || cur + self.buf.len() < offset {
827 return (stack, None);
828 }
829 let mut attrs = self.clone();
830 let mut last_off = cur + attrs.pos;
831 let mut missing = None;
832 while let Some(attr) = attrs.next() {
833 let Ok(attr) = attr else { break };
834 match attr {
835 PagePool::Id(val) => {
836 if last_off == offset {
837 stack.push(("Id", last_off));
838 break;
839 }
840 }
841 PagePool::Ifindex(val) => {
842 if last_off == offset {
843 stack.push(("Ifindex", last_off));
844 break;
845 }
846 }
847 PagePool::NapiId(val) => {
848 if last_off == offset {
849 stack.push(("NapiId", last_off));
850 break;
851 }
852 }
853 PagePool::Inflight(val) => {
854 if last_off == offset {
855 stack.push(("Inflight", last_off));
856 break;
857 }
858 }
859 PagePool::InflightMem(val) => {
860 if last_off == offset {
861 stack.push(("InflightMem", last_off));
862 break;
863 }
864 }
865 PagePool::DetachTime(val) => {
866 if last_off == offset {
867 stack.push(("DetachTime", last_off));
868 break;
869 }
870 }
871 PagePool::Dmabuf(val) => {
872 if last_off == offset {
873 stack.push(("Dmabuf", last_off));
874 break;
875 }
876 }
877 PagePool::IoUring(val) => {
878 (stack, missing) = val.lookup_attr(offset, missing_type);
879 if !stack.is_empty() {
880 break;
881 }
882 }
883 _ => {}
884 };
885 last_off = cur + attrs.pos;
886 }
887 if !stack.is_empty() {
888 stack.push(("PagePool", cur));
889 }
890 (stack, missing)
891 }
892}
893#[derive(Clone)]
894pub enum PagePoolInfo {
895 #[doc = "Unique ID of a Page Pool instance."]
896 Id(u32),
897 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
898 Ifindex(u32),
899}
900impl<'a> IterablePagePoolInfo<'a> {
901 #[doc = "Unique ID of a Page Pool instance."]
902 pub fn get_id(&self) -> Result<u32, ErrorContext> {
903 let mut iter = self.clone();
904 iter.pos = 0;
905 for attr in iter {
906 if let PagePoolInfo::Id(val) = attr? {
907 return Ok(val);
908 }
909 }
910 Err(ErrorContext::new_missing(
911 "PagePoolInfo",
912 "Id",
913 self.orig_loc,
914 self.buf.as_ptr() as usize,
915 ))
916 }
917 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
918 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
919 let mut iter = self.clone();
920 iter.pos = 0;
921 for attr in iter {
922 if let PagePoolInfo::Ifindex(val) = attr? {
923 return Ok(val);
924 }
925 }
926 Err(ErrorContext::new_missing(
927 "PagePoolInfo",
928 "Ifindex",
929 self.orig_loc,
930 self.buf.as_ptr() as usize,
931 ))
932 }
933}
934impl PagePoolInfo {
935 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolInfo<'a> {
936 IterablePagePoolInfo::with_loc(buf, buf.as_ptr() as usize)
937 }
938 fn attr_from_type(r#type: u16) -> Option<&'static str> {
939 PagePool::attr_from_type(r#type)
940 }
941}
942#[derive(Clone, Copy, Default)]
943pub struct IterablePagePoolInfo<'a> {
944 buf: &'a [u8],
945 pos: usize,
946 orig_loc: usize,
947}
948impl<'a> IterablePagePoolInfo<'a> {
949 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
950 Self {
951 buf,
952 pos: 0,
953 orig_loc,
954 }
955 }
956 pub fn get_buf(&self) -> &'a [u8] {
957 self.buf
958 }
959}
960impl<'a> Iterator for IterablePagePoolInfo<'a> {
961 type Item = Result<PagePoolInfo, ErrorContext>;
962 fn next(&mut self) -> Option<Self::Item> {
963 let pos = self.pos;
964 let mut r#type;
965 loop {
966 r#type = None;
967 if self.buf.len() == self.pos {
968 return None;
969 }
970 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
971 break;
972 };
973 r#type = Some(header.r#type);
974 let res = match header.r#type {
975 1u16 => PagePoolInfo::Id({
976 let res = parse_u32(next);
977 let Some(val) = res else { break };
978 val
979 }),
980 2u16 => PagePoolInfo::Ifindex({
981 let res = parse_u32(next);
982 let Some(val) = res else { break };
983 val
984 }),
985 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
986 n => continue,
987 };
988 return Some(Ok(res));
989 }
990 Some(Err(ErrorContext::new(
991 "PagePoolInfo",
992 r#type.and_then(|t| PagePoolInfo::attr_from_type(t)),
993 self.orig_loc,
994 self.buf.as_ptr().wrapping_add(pos) as usize,
995 )))
996 }
997}
998impl std::fmt::Debug for IterablePagePoolInfo<'_> {
999 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1000 let mut fmt = f.debug_struct("PagePoolInfo");
1001 for attr in self.clone() {
1002 let attr = match attr {
1003 Ok(a) => a,
1004 Err(err) => {
1005 fmt.finish()?;
1006 f.write_str("Err(")?;
1007 err.fmt(f)?;
1008 return f.write_str(")");
1009 }
1010 };
1011 match attr {
1012 PagePoolInfo::Id(val) => fmt.field("Id", &val),
1013 PagePoolInfo::Ifindex(val) => fmt.field("Ifindex", &val),
1014 };
1015 }
1016 fmt.finish()
1017 }
1018}
1019impl IterablePagePoolInfo<'_> {
1020 pub fn lookup_attr(
1021 &self,
1022 offset: usize,
1023 missing_type: Option<u16>,
1024 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1025 let mut stack = Vec::new();
1026 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1027 if cur == offset {
1028 stack.push(("PagePoolInfo", offset));
1029 return (
1030 stack,
1031 missing_type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1032 );
1033 }
1034 if cur > offset || cur + self.buf.len() < offset {
1035 return (stack, None);
1036 }
1037 let mut attrs = self.clone();
1038 let mut last_off = cur + attrs.pos;
1039 while let Some(attr) = attrs.next() {
1040 let Ok(attr) = attr else { break };
1041 match attr {
1042 PagePoolInfo::Id(val) => {
1043 if last_off == offset {
1044 stack.push(("Id", last_off));
1045 break;
1046 }
1047 }
1048 PagePoolInfo::Ifindex(val) => {
1049 if last_off == offset {
1050 stack.push(("Ifindex", last_off));
1051 break;
1052 }
1053 }
1054 _ => {}
1055 };
1056 last_off = cur + attrs.pos;
1057 }
1058 if !stack.is_empty() {
1059 stack.push(("PagePoolInfo", cur));
1060 }
1061 (stack, None)
1062 }
1063}
1064#[derive(Clone)]
1065pub enum PagePoolStats<'a> {
1066 #[doc = "Page pool identifying information."]
1067 Info(IterablePagePoolInfo<'a>),
1068 AllocFast(u32),
1069 AllocSlow(u32),
1070 AllocSlowHighOrder(u32),
1071 AllocEmpty(u32),
1072 AllocRefill(u32),
1073 AllocWaive(u32),
1074 RecycleCached(u32),
1075 RecycleCacheFull(u32),
1076 RecycleRing(u32),
1077 RecycleRingFull(u32),
1078 RecycleReleasedRefcnt(u32),
1079}
1080impl<'a> IterablePagePoolStats<'a> {
1081 #[doc = "Page pool identifying information."]
1082 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
1083 let mut iter = self.clone();
1084 iter.pos = 0;
1085 for attr in iter {
1086 if let PagePoolStats::Info(val) = attr? {
1087 return Ok(val);
1088 }
1089 }
1090 Err(ErrorContext::new_missing(
1091 "PagePoolStats",
1092 "Info",
1093 self.orig_loc,
1094 self.buf.as_ptr() as usize,
1095 ))
1096 }
1097 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
1098 let mut iter = self.clone();
1099 iter.pos = 0;
1100 for attr in iter {
1101 if let PagePoolStats::AllocFast(val) = attr? {
1102 return Ok(val);
1103 }
1104 }
1105 Err(ErrorContext::new_missing(
1106 "PagePoolStats",
1107 "AllocFast",
1108 self.orig_loc,
1109 self.buf.as_ptr() as usize,
1110 ))
1111 }
1112 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
1113 let mut iter = self.clone();
1114 iter.pos = 0;
1115 for attr in iter {
1116 if let PagePoolStats::AllocSlow(val) = attr? {
1117 return Ok(val);
1118 }
1119 }
1120 Err(ErrorContext::new_missing(
1121 "PagePoolStats",
1122 "AllocSlow",
1123 self.orig_loc,
1124 self.buf.as_ptr() as usize,
1125 ))
1126 }
1127 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
1128 let mut iter = self.clone();
1129 iter.pos = 0;
1130 for attr in iter {
1131 if let PagePoolStats::AllocSlowHighOrder(val) = attr? {
1132 return Ok(val);
1133 }
1134 }
1135 Err(ErrorContext::new_missing(
1136 "PagePoolStats",
1137 "AllocSlowHighOrder",
1138 self.orig_loc,
1139 self.buf.as_ptr() as usize,
1140 ))
1141 }
1142 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
1143 let mut iter = self.clone();
1144 iter.pos = 0;
1145 for attr in iter {
1146 if let PagePoolStats::AllocEmpty(val) = attr? {
1147 return Ok(val);
1148 }
1149 }
1150 Err(ErrorContext::new_missing(
1151 "PagePoolStats",
1152 "AllocEmpty",
1153 self.orig_loc,
1154 self.buf.as_ptr() as usize,
1155 ))
1156 }
1157 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
1158 let mut iter = self.clone();
1159 iter.pos = 0;
1160 for attr in iter {
1161 if let PagePoolStats::AllocRefill(val) = attr? {
1162 return Ok(val);
1163 }
1164 }
1165 Err(ErrorContext::new_missing(
1166 "PagePoolStats",
1167 "AllocRefill",
1168 self.orig_loc,
1169 self.buf.as_ptr() as usize,
1170 ))
1171 }
1172 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
1173 let mut iter = self.clone();
1174 iter.pos = 0;
1175 for attr in iter {
1176 if let PagePoolStats::AllocWaive(val) = attr? {
1177 return Ok(val);
1178 }
1179 }
1180 Err(ErrorContext::new_missing(
1181 "PagePoolStats",
1182 "AllocWaive",
1183 self.orig_loc,
1184 self.buf.as_ptr() as usize,
1185 ))
1186 }
1187 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
1188 let mut iter = self.clone();
1189 iter.pos = 0;
1190 for attr in iter {
1191 if let PagePoolStats::RecycleCached(val) = attr? {
1192 return Ok(val);
1193 }
1194 }
1195 Err(ErrorContext::new_missing(
1196 "PagePoolStats",
1197 "RecycleCached",
1198 self.orig_loc,
1199 self.buf.as_ptr() as usize,
1200 ))
1201 }
1202 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
1203 let mut iter = self.clone();
1204 iter.pos = 0;
1205 for attr in iter {
1206 if let PagePoolStats::RecycleCacheFull(val) = attr? {
1207 return Ok(val);
1208 }
1209 }
1210 Err(ErrorContext::new_missing(
1211 "PagePoolStats",
1212 "RecycleCacheFull",
1213 self.orig_loc,
1214 self.buf.as_ptr() as usize,
1215 ))
1216 }
1217 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
1218 let mut iter = self.clone();
1219 iter.pos = 0;
1220 for attr in iter {
1221 if let PagePoolStats::RecycleRing(val) = attr? {
1222 return Ok(val);
1223 }
1224 }
1225 Err(ErrorContext::new_missing(
1226 "PagePoolStats",
1227 "RecycleRing",
1228 self.orig_loc,
1229 self.buf.as_ptr() as usize,
1230 ))
1231 }
1232 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
1233 let mut iter = self.clone();
1234 iter.pos = 0;
1235 for attr in iter {
1236 if let PagePoolStats::RecycleRingFull(val) = attr? {
1237 return Ok(val);
1238 }
1239 }
1240 Err(ErrorContext::new_missing(
1241 "PagePoolStats",
1242 "RecycleRingFull",
1243 self.orig_loc,
1244 self.buf.as_ptr() as usize,
1245 ))
1246 }
1247 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
1248 let mut iter = self.clone();
1249 iter.pos = 0;
1250 for attr in iter {
1251 if let PagePoolStats::RecycleReleasedRefcnt(val) = attr? {
1252 return Ok(val);
1253 }
1254 }
1255 Err(ErrorContext::new_missing(
1256 "PagePoolStats",
1257 "RecycleReleasedRefcnt",
1258 self.orig_loc,
1259 self.buf.as_ptr() as usize,
1260 ))
1261 }
1262}
1263impl PagePoolStats<'_> {
1264 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
1265 IterablePagePoolStats::with_loc(buf, buf.as_ptr() as usize)
1266 }
1267 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1268 let res = match r#type {
1269 1u16 => "Info",
1270 8u16 => "AllocFast",
1271 9u16 => "AllocSlow",
1272 10u16 => "AllocSlowHighOrder",
1273 11u16 => "AllocEmpty",
1274 12u16 => "AllocRefill",
1275 13u16 => "AllocWaive",
1276 14u16 => "RecycleCached",
1277 15u16 => "RecycleCacheFull",
1278 16u16 => "RecycleRing",
1279 17u16 => "RecycleRingFull",
1280 18u16 => "RecycleReleasedRefcnt",
1281 _ => return None,
1282 };
1283 Some(res)
1284 }
1285}
1286#[derive(Clone, Copy, Default)]
1287pub struct IterablePagePoolStats<'a> {
1288 buf: &'a [u8],
1289 pos: usize,
1290 orig_loc: usize,
1291}
1292impl<'a> IterablePagePoolStats<'a> {
1293 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1294 Self {
1295 buf,
1296 pos: 0,
1297 orig_loc,
1298 }
1299 }
1300 pub fn get_buf(&self) -> &'a [u8] {
1301 self.buf
1302 }
1303}
1304impl<'a> Iterator for IterablePagePoolStats<'a> {
1305 type Item = Result<PagePoolStats<'a>, ErrorContext>;
1306 fn next(&mut self) -> Option<Self::Item> {
1307 let pos = self.pos;
1308 let mut r#type;
1309 loop {
1310 r#type = None;
1311 if self.buf.len() == self.pos {
1312 return None;
1313 }
1314 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1315 break;
1316 };
1317 r#type = Some(header.r#type);
1318 let res = match header.r#type {
1319 1u16 => PagePoolStats::Info({
1320 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
1321 let Some(val) = res else { break };
1322 val
1323 }),
1324 8u16 => PagePoolStats::AllocFast({
1325 let res = parse_u32(next);
1326 let Some(val) = res else { break };
1327 val
1328 }),
1329 9u16 => PagePoolStats::AllocSlow({
1330 let res = parse_u32(next);
1331 let Some(val) = res else { break };
1332 val
1333 }),
1334 10u16 => PagePoolStats::AllocSlowHighOrder({
1335 let res = parse_u32(next);
1336 let Some(val) = res else { break };
1337 val
1338 }),
1339 11u16 => PagePoolStats::AllocEmpty({
1340 let res = parse_u32(next);
1341 let Some(val) = res else { break };
1342 val
1343 }),
1344 12u16 => PagePoolStats::AllocRefill({
1345 let res = parse_u32(next);
1346 let Some(val) = res else { break };
1347 val
1348 }),
1349 13u16 => PagePoolStats::AllocWaive({
1350 let res = parse_u32(next);
1351 let Some(val) = res else { break };
1352 val
1353 }),
1354 14u16 => PagePoolStats::RecycleCached({
1355 let res = parse_u32(next);
1356 let Some(val) = res else { break };
1357 val
1358 }),
1359 15u16 => PagePoolStats::RecycleCacheFull({
1360 let res = parse_u32(next);
1361 let Some(val) = res else { break };
1362 val
1363 }),
1364 16u16 => PagePoolStats::RecycleRing({
1365 let res = parse_u32(next);
1366 let Some(val) = res else { break };
1367 val
1368 }),
1369 17u16 => PagePoolStats::RecycleRingFull({
1370 let res = parse_u32(next);
1371 let Some(val) = res else { break };
1372 val
1373 }),
1374 18u16 => PagePoolStats::RecycleReleasedRefcnt({
1375 let res = parse_u32(next);
1376 let Some(val) = res else { break };
1377 val
1378 }),
1379 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1380 n => continue,
1381 };
1382 return Some(Ok(res));
1383 }
1384 Some(Err(ErrorContext::new(
1385 "PagePoolStats",
1386 r#type.and_then(|t| PagePoolStats::attr_from_type(t)),
1387 self.orig_loc,
1388 self.buf.as_ptr().wrapping_add(pos) as usize,
1389 )))
1390 }
1391}
1392impl<'a> std::fmt::Debug for IterablePagePoolStats<'_> {
1393 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1394 let mut fmt = f.debug_struct("PagePoolStats");
1395 for attr in self.clone() {
1396 let attr = match attr {
1397 Ok(a) => a,
1398 Err(err) => {
1399 fmt.finish()?;
1400 f.write_str("Err(")?;
1401 err.fmt(f)?;
1402 return f.write_str(")");
1403 }
1404 };
1405 match attr {
1406 PagePoolStats::Info(val) => fmt.field("Info", &val),
1407 PagePoolStats::AllocFast(val) => fmt.field("AllocFast", &val),
1408 PagePoolStats::AllocSlow(val) => fmt.field("AllocSlow", &val),
1409 PagePoolStats::AllocSlowHighOrder(val) => fmt.field("AllocSlowHighOrder", &val),
1410 PagePoolStats::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
1411 PagePoolStats::AllocRefill(val) => fmt.field("AllocRefill", &val),
1412 PagePoolStats::AllocWaive(val) => fmt.field("AllocWaive", &val),
1413 PagePoolStats::RecycleCached(val) => fmt.field("RecycleCached", &val),
1414 PagePoolStats::RecycleCacheFull(val) => fmt.field("RecycleCacheFull", &val),
1415 PagePoolStats::RecycleRing(val) => fmt.field("RecycleRing", &val),
1416 PagePoolStats::RecycleRingFull(val) => fmt.field("RecycleRingFull", &val),
1417 PagePoolStats::RecycleReleasedRefcnt(val) => {
1418 fmt.field("RecycleReleasedRefcnt", &val)
1419 }
1420 };
1421 }
1422 fmt.finish()
1423 }
1424}
1425impl IterablePagePoolStats<'_> {
1426 pub fn lookup_attr(
1427 &self,
1428 offset: usize,
1429 missing_type: Option<u16>,
1430 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1431 let mut stack = Vec::new();
1432 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1433 if cur == offset {
1434 stack.push(("PagePoolStats", offset));
1435 return (
1436 stack,
1437 missing_type.and_then(|t| PagePoolStats::attr_from_type(t)),
1438 );
1439 }
1440 if cur > offset || cur + self.buf.len() < offset {
1441 return (stack, None);
1442 }
1443 let mut attrs = self.clone();
1444 let mut last_off = cur + attrs.pos;
1445 let mut missing = None;
1446 while let Some(attr) = attrs.next() {
1447 let Ok(attr) = attr else { break };
1448 match attr {
1449 PagePoolStats::Info(val) => {
1450 (stack, missing) = val.lookup_attr(offset, missing_type);
1451 if !stack.is_empty() {
1452 break;
1453 }
1454 }
1455 PagePoolStats::AllocFast(val) => {
1456 if last_off == offset {
1457 stack.push(("AllocFast", last_off));
1458 break;
1459 }
1460 }
1461 PagePoolStats::AllocSlow(val) => {
1462 if last_off == offset {
1463 stack.push(("AllocSlow", last_off));
1464 break;
1465 }
1466 }
1467 PagePoolStats::AllocSlowHighOrder(val) => {
1468 if last_off == offset {
1469 stack.push(("AllocSlowHighOrder", last_off));
1470 break;
1471 }
1472 }
1473 PagePoolStats::AllocEmpty(val) => {
1474 if last_off == offset {
1475 stack.push(("AllocEmpty", last_off));
1476 break;
1477 }
1478 }
1479 PagePoolStats::AllocRefill(val) => {
1480 if last_off == offset {
1481 stack.push(("AllocRefill", last_off));
1482 break;
1483 }
1484 }
1485 PagePoolStats::AllocWaive(val) => {
1486 if last_off == offset {
1487 stack.push(("AllocWaive", last_off));
1488 break;
1489 }
1490 }
1491 PagePoolStats::RecycleCached(val) => {
1492 if last_off == offset {
1493 stack.push(("RecycleCached", last_off));
1494 break;
1495 }
1496 }
1497 PagePoolStats::RecycleCacheFull(val) => {
1498 if last_off == offset {
1499 stack.push(("RecycleCacheFull", last_off));
1500 break;
1501 }
1502 }
1503 PagePoolStats::RecycleRing(val) => {
1504 if last_off == offset {
1505 stack.push(("RecycleRing", last_off));
1506 break;
1507 }
1508 }
1509 PagePoolStats::RecycleRingFull(val) => {
1510 if last_off == offset {
1511 stack.push(("RecycleRingFull", last_off));
1512 break;
1513 }
1514 }
1515 PagePoolStats::RecycleReleasedRefcnt(val) => {
1516 if last_off == offset {
1517 stack.push(("RecycleReleasedRefcnt", last_off));
1518 break;
1519 }
1520 }
1521 _ => {}
1522 };
1523 last_off = cur + attrs.pos;
1524 }
1525 if !stack.is_empty() {
1526 stack.push(("PagePoolStats", cur));
1527 }
1528 (stack, missing)
1529 }
1530}
1531#[derive(Clone)]
1532pub enum Napi {
1533 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1534 Ifindex(u32),
1535 #[doc = "ID of the NAPI instance."]
1536 Id(u32),
1537 #[doc = "The associated interrupt vector number for the napi"]
1538 Irq(u32),
1539 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
1540 Pid(u32),
1541 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1542 DeferHardIrqs(u32),
1543 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
1544 GroFlushTimeout(u32),
1545 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1546 IrqSuspendTimeout(u32),
1547 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
1548 Threaded(u32),
1549}
1550impl<'a> IterableNapi<'a> {
1551 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1552 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1553 let mut iter = self.clone();
1554 iter.pos = 0;
1555 for attr in iter {
1556 if let Napi::Ifindex(val) = attr? {
1557 return Ok(val);
1558 }
1559 }
1560 Err(ErrorContext::new_missing(
1561 "Napi",
1562 "Ifindex",
1563 self.orig_loc,
1564 self.buf.as_ptr() as usize,
1565 ))
1566 }
1567 #[doc = "ID of the NAPI instance."]
1568 pub fn get_id(&self) -> Result<u32, ErrorContext> {
1569 let mut iter = self.clone();
1570 iter.pos = 0;
1571 for attr in iter {
1572 if let Napi::Id(val) = attr? {
1573 return Ok(val);
1574 }
1575 }
1576 Err(ErrorContext::new_missing(
1577 "Napi",
1578 "Id",
1579 self.orig_loc,
1580 self.buf.as_ptr() as usize,
1581 ))
1582 }
1583 #[doc = "The associated interrupt vector number for the napi"]
1584 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
1585 let mut iter = self.clone();
1586 iter.pos = 0;
1587 for attr in iter {
1588 if let Napi::Irq(val) = attr? {
1589 return Ok(val);
1590 }
1591 }
1592 Err(ErrorContext::new_missing(
1593 "Napi",
1594 "Irq",
1595 self.orig_loc,
1596 self.buf.as_ptr() as usize,
1597 ))
1598 }
1599 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
1600 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
1601 let mut iter = self.clone();
1602 iter.pos = 0;
1603 for attr in iter {
1604 if let Napi::Pid(val) = attr? {
1605 return Ok(val);
1606 }
1607 }
1608 Err(ErrorContext::new_missing(
1609 "Napi",
1610 "Pid",
1611 self.orig_loc,
1612 self.buf.as_ptr() as usize,
1613 ))
1614 }
1615 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1616 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
1617 let mut iter = self.clone();
1618 iter.pos = 0;
1619 for attr in iter {
1620 if let Napi::DeferHardIrqs(val) = attr? {
1621 return Ok(val);
1622 }
1623 }
1624 Err(ErrorContext::new_missing(
1625 "Napi",
1626 "DeferHardIrqs",
1627 self.orig_loc,
1628 self.buf.as_ptr() as usize,
1629 ))
1630 }
1631 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
1632 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
1633 let mut iter = self.clone();
1634 iter.pos = 0;
1635 for attr in iter {
1636 if let Napi::GroFlushTimeout(val) = attr? {
1637 return Ok(val);
1638 }
1639 }
1640 Err(ErrorContext::new_missing(
1641 "Napi",
1642 "GroFlushTimeout",
1643 self.orig_loc,
1644 self.buf.as_ptr() as usize,
1645 ))
1646 }
1647 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1648 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
1649 let mut iter = self.clone();
1650 iter.pos = 0;
1651 for attr in iter {
1652 if let Napi::IrqSuspendTimeout(val) = attr? {
1653 return Ok(val);
1654 }
1655 }
1656 Err(ErrorContext::new_missing(
1657 "Napi",
1658 "IrqSuspendTimeout",
1659 self.orig_loc,
1660 self.buf.as_ptr() as usize,
1661 ))
1662 }
1663 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
1664 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
1665 let mut iter = self.clone();
1666 iter.pos = 0;
1667 for attr in iter {
1668 if let Napi::Threaded(val) = attr? {
1669 return Ok(val);
1670 }
1671 }
1672 Err(ErrorContext::new_missing(
1673 "Napi",
1674 "Threaded",
1675 self.orig_loc,
1676 self.buf.as_ptr() as usize,
1677 ))
1678 }
1679}
1680impl Napi {
1681 pub fn new<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
1682 IterableNapi::with_loc(buf, buf.as_ptr() as usize)
1683 }
1684 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1685 let res = match r#type {
1686 1u16 => "Ifindex",
1687 2u16 => "Id",
1688 3u16 => "Irq",
1689 4u16 => "Pid",
1690 5u16 => "DeferHardIrqs",
1691 6u16 => "GroFlushTimeout",
1692 7u16 => "IrqSuspendTimeout",
1693 8u16 => "Threaded",
1694 _ => return None,
1695 };
1696 Some(res)
1697 }
1698}
1699#[derive(Clone, Copy, Default)]
1700pub struct IterableNapi<'a> {
1701 buf: &'a [u8],
1702 pos: usize,
1703 orig_loc: usize,
1704}
1705impl<'a> IterableNapi<'a> {
1706 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1707 Self {
1708 buf,
1709 pos: 0,
1710 orig_loc,
1711 }
1712 }
1713 pub fn get_buf(&self) -> &'a [u8] {
1714 self.buf
1715 }
1716}
1717impl<'a> Iterator for IterableNapi<'a> {
1718 type Item = Result<Napi, ErrorContext>;
1719 fn next(&mut self) -> Option<Self::Item> {
1720 let pos = self.pos;
1721 let mut r#type;
1722 loop {
1723 r#type = None;
1724 if self.buf.len() == self.pos {
1725 return None;
1726 }
1727 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1728 break;
1729 };
1730 r#type = Some(header.r#type);
1731 let res = match header.r#type {
1732 1u16 => Napi::Ifindex({
1733 let res = parse_u32(next);
1734 let Some(val) = res else { break };
1735 val
1736 }),
1737 2u16 => Napi::Id({
1738 let res = parse_u32(next);
1739 let Some(val) = res else { break };
1740 val
1741 }),
1742 3u16 => Napi::Irq({
1743 let res = parse_u32(next);
1744 let Some(val) = res else { break };
1745 val
1746 }),
1747 4u16 => Napi::Pid({
1748 let res = parse_u32(next);
1749 let Some(val) = res else { break };
1750 val
1751 }),
1752 5u16 => Napi::DeferHardIrqs({
1753 let res = parse_u32(next);
1754 let Some(val) = res else { break };
1755 val
1756 }),
1757 6u16 => Napi::GroFlushTimeout({
1758 let res = parse_u32(next);
1759 let Some(val) = res else { break };
1760 val
1761 }),
1762 7u16 => Napi::IrqSuspendTimeout({
1763 let res = parse_u32(next);
1764 let Some(val) = res else { break };
1765 val
1766 }),
1767 8u16 => Napi::Threaded({
1768 let res = parse_u32(next);
1769 let Some(val) = res else { break };
1770 val
1771 }),
1772 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1773 n => continue,
1774 };
1775 return Some(Ok(res));
1776 }
1777 Some(Err(ErrorContext::new(
1778 "Napi",
1779 r#type.and_then(|t| Napi::attr_from_type(t)),
1780 self.orig_loc,
1781 self.buf.as_ptr().wrapping_add(pos) as usize,
1782 )))
1783 }
1784}
1785impl std::fmt::Debug for IterableNapi<'_> {
1786 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1787 let mut fmt = f.debug_struct("Napi");
1788 for attr in self.clone() {
1789 let attr = match attr {
1790 Ok(a) => a,
1791 Err(err) => {
1792 fmt.finish()?;
1793 f.write_str("Err(")?;
1794 err.fmt(f)?;
1795 return f.write_str(")");
1796 }
1797 };
1798 match attr {
1799 Napi::Ifindex(val) => fmt.field("Ifindex", &val),
1800 Napi::Id(val) => fmt.field("Id", &val),
1801 Napi::Irq(val) => fmt.field("Irq", &val),
1802 Napi::Pid(val) => fmt.field("Pid", &val),
1803 Napi::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
1804 Napi::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
1805 Napi::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
1806 Napi::Threaded(val) => fmt.field(
1807 "Threaded",
1808 &FormatEnum(val.into(), NapiThreaded::from_value),
1809 ),
1810 };
1811 }
1812 fmt.finish()
1813 }
1814}
1815impl IterableNapi<'_> {
1816 pub fn lookup_attr(
1817 &self,
1818 offset: usize,
1819 missing_type: Option<u16>,
1820 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1821 let mut stack = Vec::new();
1822 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1823 if cur == offset {
1824 stack.push(("Napi", offset));
1825 return (stack, missing_type.and_then(|t| Napi::attr_from_type(t)));
1826 }
1827 if cur > offset || cur + self.buf.len() < offset {
1828 return (stack, None);
1829 }
1830 let mut attrs = self.clone();
1831 let mut last_off = cur + attrs.pos;
1832 while let Some(attr) = attrs.next() {
1833 let Ok(attr) = attr else { break };
1834 match attr {
1835 Napi::Ifindex(val) => {
1836 if last_off == offset {
1837 stack.push(("Ifindex", last_off));
1838 break;
1839 }
1840 }
1841 Napi::Id(val) => {
1842 if last_off == offset {
1843 stack.push(("Id", last_off));
1844 break;
1845 }
1846 }
1847 Napi::Irq(val) => {
1848 if last_off == offset {
1849 stack.push(("Irq", last_off));
1850 break;
1851 }
1852 }
1853 Napi::Pid(val) => {
1854 if last_off == offset {
1855 stack.push(("Pid", last_off));
1856 break;
1857 }
1858 }
1859 Napi::DeferHardIrqs(val) => {
1860 if last_off == offset {
1861 stack.push(("DeferHardIrqs", last_off));
1862 break;
1863 }
1864 }
1865 Napi::GroFlushTimeout(val) => {
1866 if last_off == offset {
1867 stack.push(("GroFlushTimeout", last_off));
1868 break;
1869 }
1870 }
1871 Napi::IrqSuspendTimeout(val) => {
1872 if last_off == offset {
1873 stack.push(("IrqSuspendTimeout", last_off));
1874 break;
1875 }
1876 }
1877 Napi::Threaded(val) => {
1878 if last_off == offset {
1879 stack.push(("Threaded", last_off));
1880 break;
1881 }
1882 }
1883 _ => {}
1884 };
1885 last_off = cur + attrs.pos;
1886 }
1887 if !stack.is_empty() {
1888 stack.push(("Napi", cur));
1889 }
1890 (stack, None)
1891 }
1892}
1893#[derive(Clone)]
1894pub enum XskInfo {}
1895impl<'a> IterableXskInfo<'a> {}
1896impl XskInfo {
1897 pub fn new<'a>(buf: &'a [u8]) -> IterableXskInfo<'a> {
1898 IterableXskInfo::with_loc(buf, buf.as_ptr() as usize)
1899 }
1900 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1901 None
1902 }
1903}
1904#[derive(Clone, Copy, Default)]
1905pub struct IterableXskInfo<'a> {
1906 buf: &'a [u8],
1907 pos: usize,
1908 orig_loc: usize,
1909}
1910impl<'a> IterableXskInfo<'a> {
1911 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1912 Self {
1913 buf,
1914 pos: 0,
1915 orig_loc,
1916 }
1917 }
1918 pub fn get_buf(&self) -> &'a [u8] {
1919 self.buf
1920 }
1921}
1922impl<'a> Iterator for IterableXskInfo<'a> {
1923 type Item = Result<XskInfo, ErrorContext>;
1924 fn next(&mut self) -> Option<Self::Item> {
1925 let pos = self.pos;
1926 let mut r#type;
1927 loop {
1928 r#type = None;
1929 if self.buf.len() == self.pos {
1930 return None;
1931 }
1932 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
1933 break;
1934 };
1935 r#type = Some(header.r#type);
1936 let res = match header.r#type {
1937 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
1938 n => continue,
1939 };
1940 return Some(Ok(res));
1941 }
1942 Some(Err(ErrorContext::new(
1943 "XskInfo",
1944 r#type.and_then(|t| XskInfo::attr_from_type(t)),
1945 self.orig_loc,
1946 self.buf.as_ptr().wrapping_add(pos) as usize,
1947 )))
1948 }
1949}
1950impl std::fmt::Debug for IterableXskInfo<'_> {
1951 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1952 let mut fmt = f.debug_struct("XskInfo");
1953 for attr in self.clone() {
1954 let attr = match attr {
1955 Ok(a) => a,
1956 Err(err) => {
1957 fmt.finish()?;
1958 f.write_str("Err(")?;
1959 err.fmt(f)?;
1960 return f.write_str(")");
1961 }
1962 };
1963 match attr {};
1964 }
1965 fmt.finish()
1966 }
1967}
1968impl IterableXskInfo<'_> {
1969 pub fn lookup_attr(
1970 &self,
1971 offset: usize,
1972 missing_type: Option<u16>,
1973 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1974 let mut stack = Vec::new();
1975 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1976 if cur == offset {
1977 stack.push(("XskInfo", offset));
1978 return (stack, missing_type.and_then(|t| XskInfo::attr_from_type(t)));
1979 }
1980 (stack, None)
1981 }
1982}
1983#[derive(Clone)]
1984pub enum Queue<'a> {
1985 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
1986 Id(u32),
1987 #[doc = "ifindex of the netdevice to which the queue belongs."]
1988 Ifindex(u32),
1989 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
1990 Type(u32),
1991 #[doc = "ID of the NAPI instance which services this queue."]
1992 NapiId(u32),
1993 #[doc = "ID of the dmabuf attached to this queue, if any."]
1994 Dmabuf(u32),
1995 #[doc = "io_uring memory provider information."]
1996 IoUring(IterableIoUringProviderInfo<'a>),
1997 #[doc = "XSK information for this queue, if any."]
1998 Xsk(IterableXskInfo<'a>),
1999}
2000impl<'a> IterableQueue<'a> {
2001 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
2002 pub fn get_id(&self) -> Result<u32, ErrorContext> {
2003 let mut iter = self.clone();
2004 iter.pos = 0;
2005 for attr in iter {
2006 if let Queue::Id(val) = attr? {
2007 return Ok(val);
2008 }
2009 }
2010 Err(ErrorContext::new_missing(
2011 "Queue",
2012 "Id",
2013 self.orig_loc,
2014 self.buf.as_ptr() as usize,
2015 ))
2016 }
2017 #[doc = "ifindex of the netdevice to which the queue belongs."]
2018 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2019 let mut iter = self.clone();
2020 iter.pos = 0;
2021 for attr in iter {
2022 if let Queue::Ifindex(val) = attr? {
2023 return Ok(val);
2024 }
2025 }
2026 Err(ErrorContext::new_missing(
2027 "Queue",
2028 "Ifindex",
2029 self.orig_loc,
2030 self.buf.as_ptr() as usize,
2031 ))
2032 }
2033 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
2034 pub fn get_type(&self) -> Result<u32, ErrorContext> {
2035 let mut iter = self.clone();
2036 iter.pos = 0;
2037 for attr in iter {
2038 if let Queue::Type(val) = attr? {
2039 return Ok(val);
2040 }
2041 }
2042 Err(ErrorContext::new_missing(
2043 "Queue",
2044 "Type",
2045 self.orig_loc,
2046 self.buf.as_ptr() as usize,
2047 ))
2048 }
2049 #[doc = "ID of the NAPI instance which services this queue."]
2050 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
2051 let mut iter = self.clone();
2052 iter.pos = 0;
2053 for attr in iter {
2054 if let Queue::NapiId(val) = attr? {
2055 return Ok(val);
2056 }
2057 }
2058 Err(ErrorContext::new_missing(
2059 "Queue",
2060 "NapiId",
2061 self.orig_loc,
2062 self.buf.as_ptr() as usize,
2063 ))
2064 }
2065 #[doc = "ID of the dmabuf attached to this queue, if any."]
2066 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
2067 let mut iter = self.clone();
2068 iter.pos = 0;
2069 for attr in iter {
2070 if let Queue::Dmabuf(val) = attr? {
2071 return Ok(val);
2072 }
2073 }
2074 Err(ErrorContext::new_missing(
2075 "Queue",
2076 "Dmabuf",
2077 self.orig_loc,
2078 self.buf.as_ptr() as usize,
2079 ))
2080 }
2081 #[doc = "io_uring memory provider information."]
2082 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
2083 let mut iter = self.clone();
2084 iter.pos = 0;
2085 for attr in iter {
2086 if let Queue::IoUring(val) = attr? {
2087 return Ok(val);
2088 }
2089 }
2090 Err(ErrorContext::new_missing(
2091 "Queue",
2092 "IoUring",
2093 self.orig_loc,
2094 self.buf.as_ptr() as usize,
2095 ))
2096 }
2097 #[doc = "XSK information for this queue, if any."]
2098 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
2099 let mut iter = self.clone();
2100 iter.pos = 0;
2101 for attr in iter {
2102 if let Queue::Xsk(val) = attr? {
2103 return Ok(val);
2104 }
2105 }
2106 Err(ErrorContext::new_missing(
2107 "Queue",
2108 "Xsk",
2109 self.orig_loc,
2110 self.buf.as_ptr() as usize,
2111 ))
2112 }
2113}
2114impl Queue<'_> {
2115 pub fn new<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
2116 IterableQueue::with_loc(buf, buf.as_ptr() as usize)
2117 }
2118 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2119 let res = match r#type {
2120 1u16 => "Id",
2121 2u16 => "Ifindex",
2122 3u16 => "Type",
2123 4u16 => "NapiId",
2124 5u16 => "Dmabuf",
2125 6u16 => "IoUring",
2126 7u16 => "Xsk",
2127 _ => return None,
2128 };
2129 Some(res)
2130 }
2131}
2132#[derive(Clone, Copy, Default)]
2133pub struct IterableQueue<'a> {
2134 buf: &'a [u8],
2135 pos: usize,
2136 orig_loc: usize,
2137}
2138impl<'a> IterableQueue<'a> {
2139 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2140 Self {
2141 buf,
2142 pos: 0,
2143 orig_loc,
2144 }
2145 }
2146 pub fn get_buf(&self) -> &'a [u8] {
2147 self.buf
2148 }
2149}
2150impl<'a> Iterator for IterableQueue<'a> {
2151 type Item = Result<Queue<'a>, ErrorContext>;
2152 fn next(&mut self) -> Option<Self::Item> {
2153 let pos = self.pos;
2154 let mut r#type;
2155 loop {
2156 r#type = None;
2157 if self.buf.len() == self.pos {
2158 return None;
2159 }
2160 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2161 break;
2162 };
2163 r#type = Some(header.r#type);
2164 let res = match header.r#type {
2165 1u16 => Queue::Id({
2166 let res = parse_u32(next);
2167 let Some(val) = res else { break };
2168 val
2169 }),
2170 2u16 => Queue::Ifindex({
2171 let res = parse_u32(next);
2172 let Some(val) = res else { break };
2173 val
2174 }),
2175 3u16 => Queue::Type({
2176 let res = parse_u32(next);
2177 let Some(val) = res else { break };
2178 val
2179 }),
2180 4u16 => Queue::NapiId({
2181 let res = parse_u32(next);
2182 let Some(val) = res else { break };
2183 val
2184 }),
2185 5u16 => Queue::Dmabuf({
2186 let res = parse_u32(next);
2187 let Some(val) = res else { break };
2188 val
2189 }),
2190 6u16 => Queue::IoUring({
2191 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
2192 let Some(val) = res else { break };
2193 val
2194 }),
2195 7u16 => Queue::Xsk({
2196 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
2197 let Some(val) = res else { break };
2198 val
2199 }),
2200 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
2201 n => continue,
2202 };
2203 return Some(Ok(res));
2204 }
2205 Some(Err(ErrorContext::new(
2206 "Queue",
2207 r#type.and_then(|t| Queue::attr_from_type(t)),
2208 self.orig_loc,
2209 self.buf.as_ptr().wrapping_add(pos) as usize,
2210 )))
2211 }
2212}
2213impl<'a> std::fmt::Debug for IterableQueue<'_> {
2214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2215 let mut fmt = f.debug_struct("Queue");
2216 for attr in self.clone() {
2217 let attr = match attr {
2218 Ok(a) => a,
2219 Err(err) => {
2220 fmt.finish()?;
2221 f.write_str("Err(")?;
2222 err.fmt(f)?;
2223 return f.write_str(")");
2224 }
2225 };
2226 match attr {
2227 Queue::Id(val) => fmt.field("Id", &val),
2228 Queue::Ifindex(val) => fmt.field("Ifindex", &val),
2229 Queue::Type(val) => {
2230 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
2231 }
2232 Queue::NapiId(val) => fmt.field("NapiId", &val),
2233 Queue::Dmabuf(val) => fmt.field("Dmabuf", &val),
2234 Queue::IoUring(val) => fmt.field("IoUring", &val),
2235 Queue::Xsk(val) => fmt.field("Xsk", &val),
2236 };
2237 }
2238 fmt.finish()
2239 }
2240}
2241impl IterableQueue<'_> {
2242 pub fn lookup_attr(
2243 &self,
2244 offset: usize,
2245 missing_type: Option<u16>,
2246 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2247 let mut stack = Vec::new();
2248 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2249 if cur == offset {
2250 stack.push(("Queue", offset));
2251 return (stack, missing_type.and_then(|t| Queue::attr_from_type(t)));
2252 }
2253 if cur > offset || cur + self.buf.len() < offset {
2254 return (stack, None);
2255 }
2256 let mut attrs = self.clone();
2257 let mut last_off = cur + attrs.pos;
2258 let mut missing = None;
2259 while let Some(attr) = attrs.next() {
2260 let Ok(attr) = attr else { break };
2261 match attr {
2262 Queue::Id(val) => {
2263 if last_off == offset {
2264 stack.push(("Id", last_off));
2265 break;
2266 }
2267 }
2268 Queue::Ifindex(val) => {
2269 if last_off == offset {
2270 stack.push(("Ifindex", last_off));
2271 break;
2272 }
2273 }
2274 Queue::Type(val) => {
2275 if last_off == offset {
2276 stack.push(("Type", last_off));
2277 break;
2278 }
2279 }
2280 Queue::NapiId(val) => {
2281 if last_off == offset {
2282 stack.push(("NapiId", last_off));
2283 break;
2284 }
2285 }
2286 Queue::Dmabuf(val) => {
2287 if last_off == offset {
2288 stack.push(("Dmabuf", last_off));
2289 break;
2290 }
2291 }
2292 Queue::IoUring(val) => {
2293 (stack, missing) = val.lookup_attr(offset, missing_type);
2294 if !stack.is_empty() {
2295 break;
2296 }
2297 }
2298 Queue::Xsk(val) => {
2299 (stack, missing) = val.lookup_attr(offset, missing_type);
2300 if !stack.is_empty() {
2301 break;
2302 }
2303 }
2304 _ => {}
2305 };
2306 last_off = cur + attrs.pos;
2307 }
2308 if !stack.is_empty() {
2309 stack.push(("Queue", cur));
2310 }
2311 (stack, missing)
2312 }
2313}
2314#[derive(Clone)]
2315pub enum Qstats {
2316 #[doc = "ifindex of the netdevice to which stats belong."]
2317 Ifindex(u32),
2318 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2319 QueueType(u32),
2320 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2321 QueueId(u32),
2322 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2323 Scope(u32),
2324 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
2325 RxPackets(u32),
2326 #[doc = "Successfully received bytes, see `rx-packets`."]
2327 RxBytes(u32),
2328 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
2329 TxPackets(u32),
2330 #[doc = "Successfully sent bytes, see `tx-packets`."]
2331 TxBytes(u32),
2332 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
2333 RxAllocFail(u32),
2334 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
2335 RxHwDrops(u32),
2336 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2337 RxHwDropOverruns(u32),
2338 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2339 RxCsumComplete(u32),
2340 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2341 RxCsumUnnecessary(u32),
2342 #[doc = "Number of packets that were not checksummed by device."]
2343 RxCsumNone(u32),
2344 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2345 RxCsumBad(u32),
2346 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
2347 RxHwGroPackets(u32),
2348 #[doc = "See `rx-hw-gro-packets`."]
2349 RxHwGroBytes(u32),
2350 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2351 RxHwGroWirePackets(u32),
2352 #[doc = "See `rx-hw-gro-wire-packets`."]
2353 RxHwGroWireBytes(u32),
2354 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2355 RxHwDropRatelimits(u32),
2356 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
2357 TxHwDrops(u32),
2358 #[doc = "Number of packets dropped because they were invalid or malformed."]
2359 TxHwDropErrors(u32),
2360 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2361 TxCsumNone(u32),
2362 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
2363 TxNeedsCsum(u32),
2364 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2365 TxHwGsoPackets(u32),
2366 #[doc = "See `tx-hw-gso-packets`."]
2367 TxHwGsoBytes(u32),
2368 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2369 TxHwGsoWirePackets(u32),
2370 #[doc = "See `tx-hw-gso-wire-packets`."]
2371 TxHwGsoWireBytes(u32),
2372 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2373 TxHwDropRatelimits(u32),
2374 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
2375 TxStop(u32),
2376 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2377 TxWake(u32),
2378}
2379impl<'a> IterableQstats<'a> {
2380 #[doc = "ifindex of the netdevice to which stats belong."]
2381 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2382 let mut iter = self.clone();
2383 iter.pos = 0;
2384 for attr in iter {
2385 if let Qstats::Ifindex(val) = attr? {
2386 return Ok(val);
2387 }
2388 }
2389 Err(ErrorContext::new_missing(
2390 "Qstats",
2391 "Ifindex",
2392 self.orig_loc,
2393 self.buf.as_ptr() as usize,
2394 ))
2395 }
2396 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2397 pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
2398 let mut iter = self.clone();
2399 iter.pos = 0;
2400 for attr in iter {
2401 if let Qstats::QueueType(val) = attr? {
2402 return Ok(val);
2403 }
2404 }
2405 Err(ErrorContext::new_missing(
2406 "Qstats",
2407 "QueueType",
2408 self.orig_loc,
2409 self.buf.as_ptr() as usize,
2410 ))
2411 }
2412 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2413 pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
2414 let mut iter = self.clone();
2415 iter.pos = 0;
2416 for attr in iter {
2417 if let Qstats::QueueId(val) = attr? {
2418 return Ok(val);
2419 }
2420 }
2421 Err(ErrorContext::new_missing(
2422 "Qstats",
2423 "QueueId",
2424 self.orig_loc,
2425 self.buf.as_ptr() as usize,
2426 ))
2427 }
2428 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2429 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
2430 let mut iter = self.clone();
2431 iter.pos = 0;
2432 for attr in iter {
2433 if let Qstats::Scope(val) = attr? {
2434 return Ok(val);
2435 }
2436 }
2437 Err(ErrorContext::new_missing(
2438 "Qstats",
2439 "Scope",
2440 self.orig_loc,
2441 self.buf.as_ptr() as usize,
2442 ))
2443 }
2444 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
2445 pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
2446 let mut iter = self.clone();
2447 iter.pos = 0;
2448 for attr in iter {
2449 if let Qstats::RxPackets(val) = attr? {
2450 return Ok(val);
2451 }
2452 }
2453 Err(ErrorContext::new_missing(
2454 "Qstats",
2455 "RxPackets",
2456 self.orig_loc,
2457 self.buf.as_ptr() as usize,
2458 ))
2459 }
2460 #[doc = "Successfully received bytes, see `rx-packets`."]
2461 pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
2462 let mut iter = self.clone();
2463 iter.pos = 0;
2464 for attr in iter {
2465 if let Qstats::RxBytes(val) = attr? {
2466 return Ok(val);
2467 }
2468 }
2469 Err(ErrorContext::new_missing(
2470 "Qstats",
2471 "RxBytes",
2472 self.orig_loc,
2473 self.buf.as_ptr() as usize,
2474 ))
2475 }
2476 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
2477 pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
2478 let mut iter = self.clone();
2479 iter.pos = 0;
2480 for attr in iter {
2481 if let Qstats::TxPackets(val) = attr? {
2482 return Ok(val);
2483 }
2484 }
2485 Err(ErrorContext::new_missing(
2486 "Qstats",
2487 "TxPackets",
2488 self.orig_loc,
2489 self.buf.as_ptr() as usize,
2490 ))
2491 }
2492 #[doc = "Successfully sent bytes, see `tx-packets`."]
2493 pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
2494 let mut iter = self.clone();
2495 iter.pos = 0;
2496 for attr in iter {
2497 if let Qstats::TxBytes(val) = attr? {
2498 return Ok(val);
2499 }
2500 }
2501 Err(ErrorContext::new_missing(
2502 "Qstats",
2503 "TxBytes",
2504 self.orig_loc,
2505 self.buf.as_ptr() as usize,
2506 ))
2507 }
2508 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
2509 pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
2510 let mut iter = self.clone();
2511 iter.pos = 0;
2512 for attr in iter {
2513 if let Qstats::RxAllocFail(val) = attr? {
2514 return Ok(val);
2515 }
2516 }
2517 Err(ErrorContext::new_missing(
2518 "Qstats",
2519 "RxAllocFail",
2520 self.orig_loc,
2521 self.buf.as_ptr() as usize,
2522 ))
2523 }
2524 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
2525 pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
2526 let mut iter = self.clone();
2527 iter.pos = 0;
2528 for attr in iter {
2529 if let Qstats::RxHwDrops(val) = attr? {
2530 return Ok(val);
2531 }
2532 }
2533 Err(ErrorContext::new_missing(
2534 "Qstats",
2535 "RxHwDrops",
2536 self.orig_loc,
2537 self.buf.as_ptr() as usize,
2538 ))
2539 }
2540 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2541 pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
2542 let mut iter = self.clone();
2543 iter.pos = 0;
2544 for attr in iter {
2545 if let Qstats::RxHwDropOverruns(val) = attr? {
2546 return Ok(val);
2547 }
2548 }
2549 Err(ErrorContext::new_missing(
2550 "Qstats",
2551 "RxHwDropOverruns",
2552 self.orig_loc,
2553 self.buf.as_ptr() as usize,
2554 ))
2555 }
2556 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2557 pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
2558 let mut iter = self.clone();
2559 iter.pos = 0;
2560 for attr in iter {
2561 if let Qstats::RxCsumComplete(val) = attr? {
2562 return Ok(val);
2563 }
2564 }
2565 Err(ErrorContext::new_missing(
2566 "Qstats",
2567 "RxCsumComplete",
2568 self.orig_loc,
2569 self.buf.as_ptr() as usize,
2570 ))
2571 }
2572 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2573 pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
2574 let mut iter = self.clone();
2575 iter.pos = 0;
2576 for attr in iter {
2577 if let Qstats::RxCsumUnnecessary(val) = attr? {
2578 return Ok(val);
2579 }
2580 }
2581 Err(ErrorContext::new_missing(
2582 "Qstats",
2583 "RxCsumUnnecessary",
2584 self.orig_loc,
2585 self.buf.as_ptr() as usize,
2586 ))
2587 }
2588 #[doc = "Number of packets that were not checksummed by device."]
2589 pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
2590 let mut iter = self.clone();
2591 iter.pos = 0;
2592 for attr in iter {
2593 if let Qstats::RxCsumNone(val) = attr? {
2594 return Ok(val);
2595 }
2596 }
2597 Err(ErrorContext::new_missing(
2598 "Qstats",
2599 "RxCsumNone",
2600 self.orig_loc,
2601 self.buf.as_ptr() as usize,
2602 ))
2603 }
2604 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2605 pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
2606 let mut iter = self.clone();
2607 iter.pos = 0;
2608 for attr in iter {
2609 if let Qstats::RxCsumBad(val) = attr? {
2610 return Ok(val);
2611 }
2612 }
2613 Err(ErrorContext::new_missing(
2614 "Qstats",
2615 "RxCsumBad",
2616 self.orig_loc,
2617 self.buf.as_ptr() as usize,
2618 ))
2619 }
2620 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
2621 pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
2622 let mut iter = self.clone();
2623 iter.pos = 0;
2624 for attr in iter {
2625 if let Qstats::RxHwGroPackets(val) = attr? {
2626 return Ok(val);
2627 }
2628 }
2629 Err(ErrorContext::new_missing(
2630 "Qstats",
2631 "RxHwGroPackets",
2632 self.orig_loc,
2633 self.buf.as_ptr() as usize,
2634 ))
2635 }
2636 #[doc = "See `rx-hw-gro-packets`."]
2637 pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
2638 let mut iter = self.clone();
2639 iter.pos = 0;
2640 for attr in iter {
2641 if let Qstats::RxHwGroBytes(val) = attr? {
2642 return Ok(val);
2643 }
2644 }
2645 Err(ErrorContext::new_missing(
2646 "Qstats",
2647 "RxHwGroBytes",
2648 self.orig_loc,
2649 self.buf.as_ptr() as usize,
2650 ))
2651 }
2652 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2653 pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
2654 let mut iter = self.clone();
2655 iter.pos = 0;
2656 for attr in iter {
2657 if let Qstats::RxHwGroWirePackets(val) = attr? {
2658 return Ok(val);
2659 }
2660 }
2661 Err(ErrorContext::new_missing(
2662 "Qstats",
2663 "RxHwGroWirePackets",
2664 self.orig_loc,
2665 self.buf.as_ptr() as usize,
2666 ))
2667 }
2668 #[doc = "See `rx-hw-gro-wire-packets`."]
2669 pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
2670 let mut iter = self.clone();
2671 iter.pos = 0;
2672 for attr in iter {
2673 if let Qstats::RxHwGroWireBytes(val) = attr? {
2674 return Ok(val);
2675 }
2676 }
2677 Err(ErrorContext::new_missing(
2678 "Qstats",
2679 "RxHwGroWireBytes",
2680 self.orig_loc,
2681 self.buf.as_ptr() as usize,
2682 ))
2683 }
2684 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2685 pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2686 let mut iter = self.clone();
2687 iter.pos = 0;
2688 for attr in iter {
2689 if let Qstats::RxHwDropRatelimits(val) = attr? {
2690 return Ok(val);
2691 }
2692 }
2693 Err(ErrorContext::new_missing(
2694 "Qstats",
2695 "RxHwDropRatelimits",
2696 self.orig_loc,
2697 self.buf.as_ptr() as usize,
2698 ))
2699 }
2700 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
2701 pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
2702 let mut iter = self.clone();
2703 iter.pos = 0;
2704 for attr in iter {
2705 if let Qstats::TxHwDrops(val) = attr? {
2706 return Ok(val);
2707 }
2708 }
2709 Err(ErrorContext::new_missing(
2710 "Qstats",
2711 "TxHwDrops",
2712 self.orig_loc,
2713 self.buf.as_ptr() as usize,
2714 ))
2715 }
2716 #[doc = "Number of packets dropped because they were invalid or malformed."]
2717 pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
2718 let mut iter = self.clone();
2719 iter.pos = 0;
2720 for attr in iter {
2721 if let Qstats::TxHwDropErrors(val) = attr? {
2722 return Ok(val);
2723 }
2724 }
2725 Err(ErrorContext::new_missing(
2726 "Qstats",
2727 "TxHwDropErrors",
2728 self.orig_loc,
2729 self.buf.as_ptr() as usize,
2730 ))
2731 }
2732 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2733 pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
2734 let mut iter = self.clone();
2735 iter.pos = 0;
2736 for attr in iter {
2737 if let Qstats::TxCsumNone(val) = attr? {
2738 return Ok(val);
2739 }
2740 }
2741 Err(ErrorContext::new_missing(
2742 "Qstats",
2743 "TxCsumNone",
2744 self.orig_loc,
2745 self.buf.as_ptr() as usize,
2746 ))
2747 }
2748 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
2749 pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
2750 let mut iter = self.clone();
2751 iter.pos = 0;
2752 for attr in iter {
2753 if let Qstats::TxNeedsCsum(val) = attr? {
2754 return Ok(val);
2755 }
2756 }
2757 Err(ErrorContext::new_missing(
2758 "Qstats",
2759 "TxNeedsCsum",
2760 self.orig_loc,
2761 self.buf.as_ptr() as usize,
2762 ))
2763 }
2764 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2765 pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
2766 let mut iter = self.clone();
2767 iter.pos = 0;
2768 for attr in iter {
2769 if let Qstats::TxHwGsoPackets(val) = attr? {
2770 return Ok(val);
2771 }
2772 }
2773 Err(ErrorContext::new_missing(
2774 "Qstats",
2775 "TxHwGsoPackets",
2776 self.orig_loc,
2777 self.buf.as_ptr() as usize,
2778 ))
2779 }
2780 #[doc = "See `tx-hw-gso-packets`."]
2781 pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
2782 let mut iter = self.clone();
2783 iter.pos = 0;
2784 for attr in iter {
2785 if let Qstats::TxHwGsoBytes(val) = attr? {
2786 return Ok(val);
2787 }
2788 }
2789 Err(ErrorContext::new_missing(
2790 "Qstats",
2791 "TxHwGsoBytes",
2792 self.orig_loc,
2793 self.buf.as_ptr() as usize,
2794 ))
2795 }
2796 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2797 pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
2798 let mut iter = self.clone();
2799 iter.pos = 0;
2800 for attr in iter {
2801 if let Qstats::TxHwGsoWirePackets(val) = attr? {
2802 return Ok(val);
2803 }
2804 }
2805 Err(ErrorContext::new_missing(
2806 "Qstats",
2807 "TxHwGsoWirePackets",
2808 self.orig_loc,
2809 self.buf.as_ptr() as usize,
2810 ))
2811 }
2812 #[doc = "See `tx-hw-gso-wire-packets`."]
2813 pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
2814 let mut iter = self.clone();
2815 iter.pos = 0;
2816 for attr in iter {
2817 if let Qstats::TxHwGsoWireBytes(val) = attr? {
2818 return Ok(val);
2819 }
2820 }
2821 Err(ErrorContext::new_missing(
2822 "Qstats",
2823 "TxHwGsoWireBytes",
2824 self.orig_loc,
2825 self.buf.as_ptr() as usize,
2826 ))
2827 }
2828 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2829 pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2830 let mut iter = self.clone();
2831 iter.pos = 0;
2832 for attr in iter {
2833 if let Qstats::TxHwDropRatelimits(val) = attr? {
2834 return Ok(val);
2835 }
2836 }
2837 Err(ErrorContext::new_missing(
2838 "Qstats",
2839 "TxHwDropRatelimits",
2840 self.orig_loc,
2841 self.buf.as_ptr() as usize,
2842 ))
2843 }
2844 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
2845 pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
2846 let mut iter = self.clone();
2847 iter.pos = 0;
2848 for attr in iter {
2849 if let Qstats::TxStop(val) = attr? {
2850 return Ok(val);
2851 }
2852 }
2853 Err(ErrorContext::new_missing(
2854 "Qstats",
2855 "TxStop",
2856 self.orig_loc,
2857 self.buf.as_ptr() as usize,
2858 ))
2859 }
2860 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2861 pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
2862 let mut iter = self.clone();
2863 iter.pos = 0;
2864 for attr in iter {
2865 if let Qstats::TxWake(val) = attr? {
2866 return Ok(val);
2867 }
2868 }
2869 Err(ErrorContext::new_missing(
2870 "Qstats",
2871 "TxWake",
2872 self.orig_loc,
2873 self.buf.as_ptr() as usize,
2874 ))
2875 }
2876}
2877impl Qstats {
2878 pub fn new<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
2879 IterableQstats::with_loc(buf, buf.as_ptr() as usize)
2880 }
2881 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2882 let res = match r#type {
2883 1u16 => "Ifindex",
2884 2u16 => "QueueType",
2885 3u16 => "QueueId",
2886 4u16 => "Scope",
2887 8u16 => "RxPackets",
2888 9u16 => "RxBytes",
2889 10u16 => "TxPackets",
2890 11u16 => "TxBytes",
2891 12u16 => "RxAllocFail",
2892 13u16 => "RxHwDrops",
2893 14u16 => "RxHwDropOverruns",
2894 15u16 => "RxCsumComplete",
2895 16u16 => "RxCsumUnnecessary",
2896 17u16 => "RxCsumNone",
2897 18u16 => "RxCsumBad",
2898 19u16 => "RxHwGroPackets",
2899 20u16 => "RxHwGroBytes",
2900 21u16 => "RxHwGroWirePackets",
2901 22u16 => "RxHwGroWireBytes",
2902 23u16 => "RxHwDropRatelimits",
2903 24u16 => "TxHwDrops",
2904 25u16 => "TxHwDropErrors",
2905 26u16 => "TxCsumNone",
2906 27u16 => "TxNeedsCsum",
2907 28u16 => "TxHwGsoPackets",
2908 29u16 => "TxHwGsoBytes",
2909 30u16 => "TxHwGsoWirePackets",
2910 31u16 => "TxHwGsoWireBytes",
2911 32u16 => "TxHwDropRatelimits",
2912 33u16 => "TxStop",
2913 34u16 => "TxWake",
2914 _ => return None,
2915 };
2916 Some(res)
2917 }
2918}
2919#[derive(Clone, Copy, Default)]
2920pub struct IterableQstats<'a> {
2921 buf: &'a [u8],
2922 pos: usize,
2923 orig_loc: usize,
2924}
2925impl<'a> IterableQstats<'a> {
2926 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2927 Self {
2928 buf,
2929 pos: 0,
2930 orig_loc,
2931 }
2932 }
2933 pub fn get_buf(&self) -> &'a [u8] {
2934 self.buf
2935 }
2936}
2937impl<'a> Iterator for IterableQstats<'a> {
2938 type Item = Result<Qstats, ErrorContext>;
2939 fn next(&mut self) -> Option<Self::Item> {
2940 let pos = self.pos;
2941 let mut r#type;
2942 loop {
2943 r#type = None;
2944 if self.buf.len() == self.pos {
2945 return None;
2946 }
2947 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
2948 break;
2949 };
2950 r#type = Some(header.r#type);
2951 let res = match header.r#type {
2952 1u16 => Qstats::Ifindex({
2953 let res = parse_u32(next);
2954 let Some(val) = res else { break };
2955 val
2956 }),
2957 2u16 => Qstats::QueueType({
2958 let res = parse_u32(next);
2959 let Some(val) = res else { break };
2960 val
2961 }),
2962 3u16 => Qstats::QueueId({
2963 let res = parse_u32(next);
2964 let Some(val) = res else { break };
2965 val
2966 }),
2967 4u16 => Qstats::Scope({
2968 let res = parse_u32(next);
2969 let Some(val) = res else { break };
2970 val
2971 }),
2972 8u16 => Qstats::RxPackets({
2973 let res = parse_u32(next);
2974 let Some(val) = res else { break };
2975 val
2976 }),
2977 9u16 => Qstats::RxBytes({
2978 let res = parse_u32(next);
2979 let Some(val) = res else { break };
2980 val
2981 }),
2982 10u16 => Qstats::TxPackets({
2983 let res = parse_u32(next);
2984 let Some(val) = res else { break };
2985 val
2986 }),
2987 11u16 => Qstats::TxBytes({
2988 let res = parse_u32(next);
2989 let Some(val) = res else { break };
2990 val
2991 }),
2992 12u16 => Qstats::RxAllocFail({
2993 let res = parse_u32(next);
2994 let Some(val) = res else { break };
2995 val
2996 }),
2997 13u16 => Qstats::RxHwDrops({
2998 let res = parse_u32(next);
2999 let Some(val) = res else { break };
3000 val
3001 }),
3002 14u16 => Qstats::RxHwDropOverruns({
3003 let res = parse_u32(next);
3004 let Some(val) = res else { break };
3005 val
3006 }),
3007 15u16 => Qstats::RxCsumComplete({
3008 let res = parse_u32(next);
3009 let Some(val) = res else { break };
3010 val
3011 }),
3012 16u16 => Qstats::RxCsumUnnecessary({
3013 let res = parse_u32(next);
3014 let Some(val) = res else { break };
3015 val
3016 }),
3017 17u16 => Qstats::RxCsumNone({
3018 let res = parse_u32(next);
3019 let Some(val) = res else { break };
3020 val
3021 }),
3022 18u16 => Qstats::RxCsumBad({
3023 let res = parse_u32(next);
3024 let Some(val) = res else { break };
3025 val
3026 }),
3027 19u16 => Qstats::RxHwGroPackets({
3028 let res = parse_u32(next);
3029 let Some(val) = res else { break };
3030 val
3031 }),
3032 20u16 => Qstats::RxHwGroBytes({
3033 let res = parse_u32(next);
3034 let Some(val) = res else { break };
3035 val
3036 }),
3037 21u16 => Qstats::RxHwGroWirePackets({
3038 let res = parse_u32(next);
3039 let Some(val) = res else { break };
3040 val
3041 }),
3042 22u16 => Qstats::RxHwGroWireBytes({
3043 let res = parse_u32(next);
3044 let Some(val) = res else { break };
3045 val
3046 }),
3047 23u16 => Qstats::RxHwDropRatelimits({
3048 let res = parse_u32(next);
3049 let Some(val) = res else { break };
3050 val
3051 }),
3052 24u16 => Qstats::TxHwDrops({
3053 let res = parse_u32(next);
3054 let Some(val) = res else { break };
3055 val
3056 }),
3057 25u16 => Qstats::TxHwDropErrors({
3058 let res = parse_u32(next);
3059 let Some(val) = res else { break };
3060 val
3061 }),
3062 26u16 => Qstats::TxCsumNone({
3063 let res = parse_u32(next);
3064 let Some(val) = res else { break };
3065 val
3066 }),
3067 27u16 => Qstats::TxNeedsCsum({
3068 let res = parse_u32(next);
3069 let Some(val) = res else { break };
3070 val
3071 }),
3072 28u16 => Qstats::TxHwGsoPackets({
3073 let res = parse_u32(next);
3074 let Some(val) = res else { break };
3075 val
3076 }),
3077 29u16 => Qstats::TxHwGsoBytes({
3078 let res = parse_u32(next);
3079 let Some(val) = res else { break };
3080 val
3081 }),
3082 30u16 => Qstats::TxHwGsoWirePackets({
3083 let res = parse_u32(next);
3084 let Some(val) = res else { break };
3085 val
3086 }),
3087 31u16 => Qstats::TxHwGsoWireBytes({
3088 let res = parse_u32(next);
3089 let Some(val) = res else { break };
3090 val
3091 }),
3092 32u16 => Qstats::TxHwDropRatelimits({
3093 let res = parse_u32(next);
3094 let Some(val) = res else { break };
3095 val
3096 }),
3097 33u16 => Qstats::TxStop({
3098 let res = parse_u32(next);
3099 let Some(val) = res else { break };
3100 val
3101 }),
3102 34u16 => Qstats::TxWake({
3103 let res = parse_u32(next);
3104 let Some(val) = res else { break };
3105 val
3106 }),
3107 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3108 n => continue,
3109 };
3110 return Some(Ok(res));
3111 }
3112 Some(Err(ErrorContext::new(
3113 "Qstats",
3114 r#type.and_then(|t| Qstats::attr_from_type(t)),
3115 self.orig_loc,
3116 self.buf.as_ptr().wrapping_add(pos) as usize,
3117 )))
3118 }
3119}
3120impl std::fmt::Debug for IterableQstats<'_> {
3121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3122 let mut fmt = f.debug_struct("Qstats");
3123 for attr in self.clone() {
3124 let attr = match attr {
3125 Ok(a) => a,
3126 Err(err) => {
3127 fmt.finish()?;
3128 f.write_str("Err(")?;
3129 err.fmt(f)?;
3130 return f.write_str(")");
3131 }
3132 };
3133 match attr {
3134 Qstats::Ifindex(val) => fmt.field("Ifindex", &val),
3135 Qstats::QueueType(val) => {
3136 fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
3137 }
3138 Qstats::QueueId(val) => fmt.field("QueueId", &val),
3139 Qstats::Scope(val) => {
3140 fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
3141 }
3142 Qstats::RxPackets(val) => fmt.field("RxPackets", &val),
3143 Qstats::RxBytes(val) => fmt.field("RxBytes", &val),
3144 Qstats::TxPackets(val) => fmt.field("TxPackets", &val),
3145 Qstats::TxBytes(val) => fmt.field("TxBytes", &val),
3146 Qstats::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
3147 Qstats::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
3148 Qstats::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
3149 Qstats::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
3150 Qstats::RxCsumUnnecessary(val) => fmt.field("RxCsumUnnecessary", &val),
3151 Qstats::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
3152 Qstats::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
3153 Qstats::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
3154 Qstats::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
3155 Qstats::RxHwGroWirePackets(val) => fmt.field("RxHwGroWirePackets", &val),
3156 Qstats::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
3157 Qstats::RxHwDropRatelimits(val) => fmt.field("RxHwDropRatelimits", &val),
3158 Qstats::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
3159 Qstats::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
3160 Qstats::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
3161 Qstats::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
3162 Qstats::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
3163 Qstats::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
3164 Qstats::TxHwGsoWirePackets(val) => fmt.field("TxHwGsoWirePackets", &val),
3165 Qstats::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
3166 Qstats::TxHwDropRatelimits(val) => fmt.field("TxHwDropRatelimits", &val),
3167 Qstats::TxStop(val) => fmt.field("TxStop", &val),
3168 Qstats::TxWake(val) => fmt.field("TxWake", &val),
3169 };
3170 }
3171 fmt.finish()
3172 }
3173}
3174impl IterableQstats<'_> {
3175 pub fn lookup_attr(
3176 &self,
3177 offset: usize,
3178 missing_type: Option<u16>,
3179 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3180 let mut stack = Vec::new();
3181 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3182 if cur == offset {
3183 stack.push(("Qstats", offset));
3184 return (stack, missing_type.and_then(|t| Qstats::attr_from_type(t)));
3185 }
3186 if cur > offset || cur + self.buf.len() < offset {
3187 return (stack, None);
3188 }
3189 let mut attrs = self.clone();
3190 let mut last_off = cur + attrs.pos;
3191 while let Some(attr) = attrs.next() {
3192 let Ok(attr) = attr else { break };
3193 match attr {
3194 Qstats::Ifindex(val) => {
3195 if last_off == offset {
3196 stack.push(("Ifindex", last_off));
3197 break;
3198 }
3199 }
3200 Qstats::QueueType(val) => {
3201 if last_off == offset {
3202 stack.push(("QueueType", last_off));
3203 break;
3204 }
3205 }
3206 Qstats::QueueId(val) => {
3207 if last_off == offset {
3208 stack.push(("QueueId", last_off));
3209 break;
3210 }
3211 }
3212 Qstats::Scope(val) => {
3213 if last_off == offset {
3214 stack.push(("Scope", last_off));
3215 break;
3216 }
3217 }
3218 Qstats::RxPackets(val) => {
3219 if last_off == offset {
3220 stack.push(("RxPackets", last_off));
3221 break;
3222 }
3223 }
3224 Qstats::RxBytes(val) => {
3225 if last_off == offset {
3226 stack.push(("RxBytes", last_off));
3227 break;
3228 }
3229 }
3230 Qstats::TxPackets(val) => {
3231 if last_off == offset {
3232 stack.push(("TxPackets", last_off));
3233 break;
3234 }
3235 }
3236 Qstats::TxBytes(val) => {
3237 if last_off == offset {
3238 stack.push(("TxBytes", last_off));
3239 break;
3240 }
3241 }
3242 Qstats::RxAllocFail(val) => {
3243 if last_off == offset {
3244 stack.push(("RxAllocFail", last_off));
3245 break;
3246 }
3247 }
3248 Qstats::RxHwDrops(val) => {
3249 if last_off == offset {
3250 stack.push(("RxHwDrops", last_off));
3251 break;
3252 }
3253 }
3254 Qstats::RxHwDropOverruns(val) => {
3255 if last_off == offset {
3256 stack.push(("RxHwDropOverruns", last_off));
3257 break;
3258 }
3259 }
3260 Qstats::RxCsumComplete(val) => {
3261 if last_off == offset {
3262 stack.push(("RxCsumComplete", last_off));
3263 break;
3264 }
3265 }
3266 Qstats::RxCsumUnnecessary(val) => {
3267 if last_off == offset {
3268 stack.push(("RxCsumUnnecessary", last_off));
3269 break;
3270 }
3271 }
3272 Qstats::RxCsumNone(val) => {
3273 if last_off == offset {
3274 stack.push(("RxCsumNone", last_off));
3275 break;
3276 }
3277 }
3278 Qstats::RxCsumBad(val) => {
3279 if last_off == offset {
3280 stack.push(("RxCsumBad", last_off));
3281 break;
3282 }
3283 }
3284 Qstats::RxHwGroPackets(val) => {
3285 if last_off == offset {
3286 stack.push(("RxHwGroPackets", last_off));
3287 break;
3288 }
3289 }
3290 Qstats::RxHwGroBytes(val) => {
3291 if last_off == offset {
3292 stack.push(("RxHwGroBytes", last_off));
3293 break;
3294 }
3295 }
3296 Qstats::RxHwGroWirePackets(val) => {
3297 if last_off == offset {
3298 stack.push(("RxHwGroWirePackets", last_off));
3299 break;
3300 }
3301 }
3302 Qstats::RxHwGroWireBytes(val) => {
3303 if last_off == offset {
3304 stack.push(("RxHwGroWireBytes", last_off));
3305 break;
3306 }
3307 }
3308 Qstats::RxHwDropRatelimits(val) => {
3309 if last_off == offset {
3310 stack.push(("RxHwDropRatelimits", last_off));
3311 break;
3312 }
3313 }
3314 Qstats::TxHwDrops(val) => {
3315 if last_off == offset {
3316 stack.push(("TxHwDrops", last_off));
3317 break;
3318 }
3319 }
3320 Qstats::TxHwDropErrors(val) => {
3321 if last_off == offset {
3322 stack.push(("TxHwDropErrors", last_off));
3323 break;
3324 }
3325 }
3326 Qstats::TxCsumNone(val) => {
3327 if last_off == offset {
3328 stack.push(("TxCsumNone", last_off));
3329 break;
3330 }
3331 }
3332 Qstats::TxNeedsCsum(val) => {
3333 if last_off == offset {
3334 stack.push(("TxNeedsCsum", last_off));
3335 break;
3336 }
3337 }
3338 Qstats::TxHwGsoPackets(val) => {
3339 if last_off == offset {
3340 stack.push(("TxHwGsoPackets", last_off));
3341 break;
3342 }
3343 }
3344 Qstats::TxHwGsoBytes(val) => {
3345 if last_off == offset {
3346 stack.push(("TxHwGsoBytes", last_off));
3347 break;
3348 }
3349 }
3350 Qstats::TxHwGsoWirePackets(val) => {
3351 if last_off == offset {
3352 stack.push(("TxHwGsoWirePackets", last_off));
3353 break;
3354 }
3355 }
3356 Qstats::TxHwGsoWireBytes(val) => {
3357 if last_off == offset {
3358 stack.push(("TxHwGsoWireBytes", last_off));
3359 break;
3360 }
3361 }
3362 Qstats::TxHwDropRatelimits(val) => {
3363 if last_off == offset {
3364 stack.push(("TxHwDropRatelimits", last_off));
3365 break;
3366 }
3367 }
3368 Qstats::TxStop(val) => {
3369 if last_off == offset {
3370 stack.push(("TxStop", last_off));
3371 break;
3372 }
3373 }
3374 Qstats::TxWake(val) => {
3375 if last_off == offset {
3376 stack.push(("TxWake", last_off));
3377 break;
3378 }
3379 }
3380 _ => {}
3381 };
3382 last_off = cur + attrs.pos;
3383 }
3384 if !stack.is_empty() {
3385 stack.push(("Qstats", cur));
3386 }
3387 (stack, None)
3388 }
3389}
3390#[derive(Clone)]
3391pub enum QueueId {
3392 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
3393 Id(u32),
3394 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
3395 Type(u32),
3396}
3397impl<'a> IterableQueueId<'a> {
3398 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
3399 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3400 let mut iter = self.clone();
3401 iter.pos = 0;
3402 for attr in iter {
3403 if let QueueId::Id(val) = attr? {
3404 return Ok(val);
3405 }
3406 }
3407 Err(ErrorContext::new_missing(
3408 "QueueId",
3409 "Id",
3410 self.orig_loc,
3411 self.buf.as_ptr() as usize,
3412 ))
3413 }
3414 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
3415 pub fn get_type(&self) -> Result<u32, ErrorContext> {
3416 let mut iter = self.clone();
3417 iter.pos = 0;
3418 for attr in iter {
3419 if let QueueId::Type(val) = attr? {
3420 return Ok(val);
3421 }
3422 }
3423 Err(ErrorContext::new_missing(
3424 "QueueId",
3425 "Type",
3426 self.orig_loc,
3427 self.buf.as_ptr() as usize,
3428 ))
3429 }
3430}
3431impl QueueId {
3432 pub fn new<'a>(buf: &'a [u8]) -> IterableQueueId<'a> {
3433 IterableQueueId::with_loc(buf, buf.as_ptr() as usize)
3434 }
3435 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3436 Queue::attr_from_type(r#type)
3437 }
3438}
3439#[derive(Clone, Copy, Default)]
3440pub struct IterableQueueId<'a> {
3441 buf: &'a [u8],
3442 pos: usize,
3443 orig_loc: usize,
3444}
3445impl<'a> IterableQueueId<'a> {
3446 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3447 Self {
3448 buf,
3449 pos: 0,
3450 orig_loc,
3451 }
3452 }
3453 pub fn get_buf(&self) -> &'a [u8] {
3454 self.buf
3455 }
3456}
3457impl<'a> Iterator for IterableQueueId<'a> {
3458 type Item = Result<QueueId, ErrorContext>;
3459 fn next(&mut self) -> Option<Self::Item> {
3460 let pos = self.pos;
3461 let mut r#type;
3462 loop {
3463 r#type = None;
3464 if self.buf.len() == self.pos {
3465 return None;
3466 }
3467 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3468 break;
3469 };
3470 r#type = Some(header.r#type);
3471 let res = match header.r#type {
3472 1u16 => QueueId::Id({
3473 let res = parse_u32(next);
3474 let Some(val) = res else { break };
3475 val
3476 }),
3477 3u16 => QueueId::Type({
3478 let res = parse_u32(next);
3479 let Some(val) = res else { break };
3480 val
3481 }),
3482 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3483 n => continue,
3484 };
3485 return Some(Ok(res));
3486 }
3487 Some(Err(ErrorContext::new(
3488 "QueueId",
3489 r#type.and_then(|t| QueueId::attr_from_type(t)),
3490 self.orig_loc,
3491 self.buf.as_ptr().wrapping_add(pos) as usize,
3492 )))
3493 }
3494}
3495impl std::fmt::Debug for IterableQueueId<'_> {
3496 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3497 let mut fmt = f.debug_struct("QueueId");
3498 for attr in self.clone() {
3499 let attr = match attr {
3500 Ok(a) => a,
3501 Err(err) => {
3502 fmt.finish()?;
3503 f.write_str("Err(")?;
3504 err.fmt(f)?;
3505 return f.write_str(")");
3506 }
3507 };
3508 match attr {
3509 QueueId::Id(val) => fmt.field("Id", &val),
3510 QueueId::Type(val) => {
3511 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
3512 }
3513 };
3514 }
3515 fmt.finish()
3516 }
3517}
3518impl IterableQueueId<'_> {
3519 pub fn lookup_attr(
3520 &self,
3521 offset: usize,
3522 missing_type: Option<u16>,
3523 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3524 let mut stack = Vec::new();
3525 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3526 if cur == offset {
3527 stack.push(("QueueId", offset));
3528 return (stack, missing_type.and_then(|t| QueueId::attr_from_type(t)));
3529 }
3530 if cur > offset || cur + self.buf.len() < offset {
3531 return (stack, None);
3532 }
3533 let mut attrs = self.clone();
3534 let mut last_off = cur + attrs.pos;
3535 while let Some(attr) = attrs.next() {
3536 let Ok(attr) = attr else { break };
3537 match attr {
3538 QueueId::Id(val) => {
3539 if last_off == offset {
3540 stack.push(("Id", last_off));
3541 break;
3542 }
3543 }
3544 QueueId::Type(val) => {
3545 if last_off == offset {
3546 stack.push(("Type", last_off));
3547 break;
3548 }
3549 }
3550 _ => {}
3551 };
3552 last_off = cur + attrs.pos;
3553 }
3554 if !stack.is_empty() {
3555 stack.push(("QueueId", cur));
3556 }
3557 (stack, None)
3558 }
3559}
3560#[derive(Clone)]
3561pub enum Dmabuf<'a> {
3562 #[doc = "netdev ifindex to bind the dmabuf to."]
3563 Ifindex(u32),
3564 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3565 Queues(IterableQueueId<'a>),
3566 #[doc = "dmabuf file descriptor to bind."]
3567 Fd(u32),
3568 #[doc = "id of the dmabuf binding"]
3569 Id(u32),
3570}
3571impl<'a> IterableDmabuf<'a> {
3572 #[doc = "netdev ifindex to bind the dmabuf to."]
3573 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3574 let mut iter = self.clone();
3575 iter.pos = 0;
3576 for attr in iter {
3577 if let Dmabuf::Ifindex(val) = attr? {
3578 return Ok(val);
3579 }
3580 }
3581 Err(ErrorContext::new_missing(
3582 "Dmabuf",
3583 "Ifindex",
3584 self.orig_loc,
3585 self.buf.as_ptr() as usize,
3586 ))
3587 }
3588 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3589 pub fn get_queues(&self) -> MultiAttrIterable<Self, Dmabuf<'a>, IterableQueueId<'a>> {
3590 MultiAttrIterable::new(self.clone(), |variant| {
3591 if let Dmabuf::Queues(val) = variant {
3592 Some(val)
3593 } else {
3594 None
3595 }
3596 })
3597 }
3598 #[doc = "dmabuf file descriptor to bind."]
3599 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
3600 let mut iter = self.clone();
3601 iter.pos = 0;
3602 for attr in iter {
3603 if let Dmabuf::Fd(val) = attr? {
3604 return Ok(val);
3605 }
3606 }
3607 Err(ErrorContext::new_missing(
3608 "Dmabuf",
3609 "Fd",
3610 self.orig_loc,
3611 self.buf.as_ptr() as usize,
3612 ))
3613 }
3614 #[doc = "id of the dmabuf binding"]
3615 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3616 let mut iter = self.clone();
3617 iter.pos = 0;
3618 for attr in iter {
3619 if let Dmabuf::Id(val) = attr? {
3620 return Ok(val);
3621 }
3622 }
3623 Err(ErrorContext::new_missing(
3624 "Dmabuf",
3625 "Id",
3626 self.orig_loc,
3627 self.buf.as_ptr() as usize,
3628 ))
3629 }
3630}
3631impl Dmabuf<'_> {
3632 pub fn new<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
3633 IterableDmabuf::with_loc(buf, buf.as_ptr() as usize)
3634 }
3635 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3636 let res = match r#type {
3637 1u16 => "Ifindex",
3638 2u16 => "Queues",
3639 3u16 => "Fd",
3640 4u16 => "Id",
3641 _ => return None,
3642 };
3643 Some(res)
3644 }
3645}
3646#[derive(Clone, Copy, Default)]
3647pub struct IterableDmabuf<'a> {
3648 buf: &'a [u8],
3649 pos: usize,
3650 orig_loc: usize,
3651}
3652impl<'a> IterableDmabuf<'a> {
3653 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3654 Self {
3655 buf,
3656 pos: 0,
3657 orig_loc,
3658 }
3659 }
3660 pub fn get_buf(&self) -> &'a [u8] {
3661 self.buf
3662 }
3663}
3664impl<'a> Iterator for IterableDmabuf<'a> {
3665 type Item = Result<Dmabuf<'a>, ErrorContext>;
3666 fn next(&mut self) -> Option<Self::Item> {
3667 let pos = self.pos;
3668 let mut r#type;
3669 loop {
3670 r#type = None;
3671 if self.buf.len() == self.pos {
3672 return None;
3673 }
3674 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
3675 break;
3676 };
3677 r#type = Some(header.r#type);
3678 let res = match header.r#type {
3679 1u16 => Dmabuf::Ifindex({
3680 let res = parse_u32(next);
3681 let Some(val) = res else { break };
3682 val
3683 }),
3684 2u16 => Dmabuf::Queues({
3685 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3686 let Some(val) = res else { break };
3687 val
3688 }),
3689 3u16 => Dmabuf::Fd({
3690 let res = parse_u32(next);
3691 let Some(val) = res else { break };
3692 val
3693 }),
3694 4u16 => Dmabuf::Id({
3695 let res = parse_u32(next);
3696 let Some(val) = res else { break };
3697 val
3698 }),
3699 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
3700 n => continue,
3701 };
3702 return Some(Ok(res));
3703 }
3704 Some(Err(ErrorContext::new(
3705 "Dmabuf",
3706 r#type.and_then(|t| Dmabuf::attr_from_type(t)),
3707 self.orig_loc,
3708 self.buf.as_ptr().wrapping_add(pos) as usize,
3709 )))
3710 }
3711}
3712impl<'a> std::fmt::Debug for IterableDmabuf<'_> {
3713 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3714 let mut fmt = f.debug_struct("Dmabuf");
3715 for attr in self.clone() {
3716 let attr = match attr {
3717 Ok(a) => a,
3718 Err(err) => {
3719 fmt.finish()?;
3720 f.write_str("Err(")?;
3721 err.fmt(f)?;
3722 return f.write_str(")");
3723 }
3724 };
3725 match attr {
3726 Dmabuf::Ifindex(val) => fmt.field("Ifindex", &val),
3727 Dmabuf::Queues(val) => fmt.field("Queues", &val),
3728 Dmabuf::Fd(val) => fmt.field("Fd", &val),
3729 Dmabuf::Id(val) => fmt.field("Id", &val),
3730 };
3731 }
3732 fmt.finish()
3733 }
3734}
3735impl IterableDmabuf<'_> {
3736 pub fn lookup_attr(
3737 &self,
3738 offset: usize,
3739 missing_type: Option<u16>,
3740 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3741 let mut stack = Vec::new();
3742 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3743 if cur == offset {
3744 stack.push(("Dmabuf", offset));
3745 return (stack, missing_type.and_then(|t| Dmabuf::attr_from_type(t)));
3746 }
3747 if cur > offset || cur + self.buf.len() < offset {
3748 return (stack, None);
3749 }
3750 let mut attrs = self.clone();
3751 let mut last_off = cur + attrs.pos;
3752 let mut missing = None;
3753 while let Some(attr) = attrs.next() {
3754 let Ok(attr) = attr else { break };
3755 match attr {
3756 Dmabuf::Ifindex(val) => {
3757 if last_off == offset {
3758 stack.push(("Ifindex", last_off));
3759 break;
3760 }
3761 }
3762 Dmabuf::Queues(val) => {
3763 (stack, missing) = val.lookup_attr(offset, missing_type);
3764 if !stack.is_empty() {
3765 break;
3766 }
3767 }
3768 Dmabuf::Fd(val) => {
3769 if last_off == offset {
3770 stack.push(("Fd", last_off));
3771 break;
3772 }
3773 }
3774 Dmabuf::Id(val) => {
3775 if last_off == offset {
3776 stack.push(("Id", last_off));
3777 break;
3778 }
3779 }
3780 _ => {}
3781 };
3782 last_off = cur + attrs.pos;
3783 }
3784 if !stack.is_empty() {
3785 stack.push(("Dmabuf", cur));
3786 }
3787 (stack, missing)
3788 }
3789}
3790pub struct PushDev<Prev: Rec> {
3791 pub(crate) prev: Option<Prev>,
3792 pub(crate) header_offset: Option<usize>,
3793}
3794impl<Prev: Rec> Rec for PushDev<Prev> {
3795 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3796 self.prev.as_mut().unwrap().as_rec_mut()
3797 }
3798 fn as_rec(&self) -> &Vec<u8> {
3799 self.prev.as_ref().unwrap().as_rec()
3800 }
3801}
3802impl<Prev: Rec> PushDev<Prev> {
3803 pub fn new(prev: Prev) -> Self {
3804 Self {
3805 prev: Some(prev),
3806 header_offset: None,
3807 }
3808 }
3809 pub fn end_nested(mut self) -> Prev {
3810 let mut prev = self.prev.take().unwrap();
3811 if let Some(header_offset) = &self.header_offset {
3812 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3813 }
3814 prev
3815 }
3816 #[doc = "netdev ifindex"]
3817 pub fn push_ifindex(mut self, value: u32) -> Self {
3818 push_header(self.as_rec_mut(), 1u16, 4 as u16);
3819 self.as_rec_mut().extend(value.to_ne_bytes());
3820 self
3821 }
3822 pub fn push_pad(mut self, value: &[u8]) -> Self {
3823 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
3824 self.as_rec_mut().extend(value);
3825 self
3826 }
3827 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
3828 pub fn push_xdp_features(mut self, value: u64) -> Self {
3829 push_header(self.as_rec_mut(), 3u16, 8 as u16);
3830 self.as_rec_mut().extend(value.to_ne_bytes());
3831 self
3832 }
3833 #[doc = "max fragment count supported by ZC driver"]
3834 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
3835 push_header(self.as_rec_mut(), 4u16, 4 as u16);
3836 self.as_rec_mut().extend(value.to_ne_bytes());
3837 self
3838 }
3839 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
3840 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
3841 push_header(self.as_rec_mut(), 5u16, 8 as u16);
3842 self.as_rec_mut().extend(value.to_ne_bytes());
3843 self
3844 }
3845 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
3846 pub fn push_xsk_features(mut self, value: u64) -> Self {
3847 push_header(self.as_rec_mut(), 6u16, 8 as u16);
3848 self.as_rec_mut().extend(value.to_ne_bytes());
3849 self
3850 }
3851}
3852impl<Prev: Rec> Drop for PushDev<Prev> {
3853 fn drop(&mut self) {
3854 if let Some(prev) = &mut self.prev {
3855 if let Some(header_offset) = &self.header_offset {
3856 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3857 }
3858 }
3859 }
3860}
3861pub struct PushIoUringProviderInfo<Prev: Rec> {
3862 pub(crate) prev: Option<Prev>,
3863 pub(crate) header_offset: Option<usize>,
3864}
3865impl<Prev: Rec> Rec for PushIoUringProviderInfo<Prev> {
3866 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3867 self.prev.as_mut().unwrap().as_rec_mut()
3868 }
3869 fn as_rec(&self) -> &Vec<u8> {
3870 self.prev.as_ref().unwrap().as_rec()
3871 }
3872}
3873impl<Prev: Rec> PushIoUringProviderInfo<Prev> {
3874 pub fn new(prev: Prev) -> Self {
3875 Self {
3876 prev: Some(prev),
3877 header_offset: None,
3878 }
3879 }
3880 pub fn end_nested(mut self) -> Prev {
3881 let mut prev = self.prev.take().unwrap();
3882 if let Some(header_offset) = &self.header_offset {
3883 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3884 }
3885 prev
3886 }
3887}
3888impl<Prev: Rec> Drop for PushIoUringProviderInfo<Prev> {
3889 fn drop(&mut self) {
3890 if let Some(prev) = &mut self.prev {
3891 if let Some(header_offset) = &self.header_offset {
3892 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3893 }
3894 }
3895 }
3896}
3897pub struct PushPagePool<Prev: Rec> {
3898 pub(crate) prev: Option<Prev>,
3899 pub(crate) header_offset: Option<usize>,
3900}
3901impl<Prev: Rec> Rec for PushPagePool<Prev> {
3902 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3903 self.prev.as_mut().unwrap().as_rec_mut()
3904 }
3905 fn as_rec(&self) -> &Vec<u8> {
3906 self.prev.as_ref().unwrap().as_rec()
3907 }
3908}
3909impl<Prev: Rec> PushPagePool<Prev> {
3910 pub fn new(prev: Prev) -> Self {
3911 Self {
3912 prev: Some(prev),
3913 header_offset: None,
3914 }
3915 }
3916 pub fn end_nested(mut self) -> Prev {
3917 let mut prev = self.prev.take().unwrap();
3918 if let Some(header_offset) = &self.header_offset {
3919 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3920 }
3921 prev
3922 }
3923 #[doc = "Unique ID of a Page Pool instance."]
3924 pub fn push_id(mut self, value: u32) -> Self {
3925 push_header(self.as_rec_mut(), 1u16, 4 as u16);
3926 self.as_rec_mut().extend(value.to_ne_bytes());
3927 self
3928 }
3929 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
3930 pub fn push_ifindex(mut self, value: u32) -> Self {
3931 push_header(self.as_rec_mut(), 2u16, 4 as u16);
3932 self.as_rec_mut().extend(value.to_ne_bytes());
3933 self
3934 }
3935 #[doc = "Id of NAPI using this Page Pool instance."]
3936 pub fn push_napi_id(mut self, value: u32) -> Self {
3937 push_header(self.as_rec_mut(), 3u16, 4 as u16);
3938 self.as_rec_mut().extend(value.to_ne_bytes());
3939 self
3940 }
3941 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
3942 pub fn push_inflight(mut self, value: u32) -> Self {
3943 push_header(self.as_rec_mut(), 4u16, 4 as u16);
3944 self.as_rec_mut().extend(value.to_ne_bytes());
3945 self
3946 }
3947 #[doc = "Amount of memory held by inflight pages.\n"]
3948 pub fn push_inflight_mem(mut self, value: u32) -> Self {
3949 push_header(self.as_rec_mut(), 5u16, 4 as u16);
3950 self.as_rec_mut().extend(value.to_ne_bytes());
3951 self
3952 }
3953 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
3954 pub fn push_detach_time(mut self, value: u32) -> Self {
3955 push_header(self.as_rec_mut(), 6u16, 4 as u16);
3956 self.as_rec_mut().extend(value.to_ne_bytes());
3957 self
3958 }
3959 #[doc = "ID of the dmabuf this page-pool is attached to."]
3960 pub fn push_dmabuf(mut self, value: u32) -> Self {
3961 push_header(self.as_rec_mut(), 7u16, 4 as u16);
3962 self.as_rec_mut().extend(value.to_ne_bytes());
3963 self
3964 }
3965 #[doc = "io-uring memory provider information."]
3966 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
3967 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
3968 PushIoUringProviderInfo {
3969 prev: Some(self),
3970 header_offset: Some(header_offset),
3971 }
3972 }
3973}
3974impl<Prev: Rec> Drop for PushPagePool<Prev> {
3975 fn drop(&mut self) {
3976 if let Some(prev) = &mut self.prev {
3977 if let Some(header_offset) = &self.header_offset {
3978 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3979 }
3980 }
3981 }
3982}
3983pub struct PushPagePoolInfo<Prev: Rec> {
3984 pub(crate) prev: Option<Prev>,
3985 pub(crate) header_offset: Option<usize>,
3986}
3987impl<Prev: Rec> Rec for PushPagePoolInfo<Prev> {
3988 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3989 self.prev.as_mut().unwrap().as_rec_mut()
3990 }
3991 fn as_rec(&self) -> &Vec<u8> {
3992 self.prev.as_ref().unwrap().as_rec()
3993 }
3994}
3995impl<Prev: Rec> PushPagePoolInfo<Prev> {
3996 pub fn new(prev: Prev) -> Self {
3997 Self {
3998 prev: Some(prev),
3999 header_offset: None,
4000 }
4001 }
4002 pub fn end_nested(mut self) -> Prev {
4003 let mut prev = self.prev.take().unwrap();
4004 if let Some(header_offset) = &self.header_offset {
4005 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4006 }
4007 prev
4008 }
4009 #[doc = "Unique ID of a Page Pool instance."]
4010 pub fn push_id(mut self, value: u32) -> Self {
4011 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4012 self.as_rec_mut().extend(value.to_ne_bytes());
4013 self
4014 }
4015 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
4016 pub fn push_ifindex(mut self, value: u32) -> Self {
4017 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4018 self.as_rec_mut().extend(value.to_ne_bytes());
4019 self
4020 }
4021}
4022impl<Prev: Rec> Drop for PushPagePoolInfo<Prev> {
4023 fn drop(&mut self) {
4024 if let Some(prev) = &mut self.prev {
4025 if let Some(header_offset) = &self.header_offset {
4026 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4027 }
4028 }
4029 }
4030}
4031pub struct PushPagePoolStats<Prev: Rec> {
4032 pub(crate) prev: Option<Prev>,
4033 pub(crate) header_offset: Option<usize>,
4034}
4035impl<Prev: Rec> Rec for PushPagePoolStats<Prev> {
4036 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4037 self.prev.as_mut().unwrap().as_rec_mut()
4038 }
4039 fn as_rec(&self) -> &Vec<u8> {
4040 self.prev.as_ref().unwrap().as_rec()
4041 }
4042}
4043impl<Prev: Rec> PushPagePoolStats<Prev> {
4044 pub fn new(prev: Prev) -> Self {
4045 Self {
4046 prev: Some(prev),
4047 header_offset: None,
4048 }
4049 }
4050 pub fn end_nested(mut self) -> Prev {
4051 let mut prev = self.prev.take().unwrap();
4052 if let Some(header_offset) = &self.header_offset {
4053 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4054 }
4055 prev
4056 }
4057 #[doc = "Page pool identifying information."]
4058 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
4059 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4060 PushPagePoolInfo {
4061 prev: Some(self),
4062 header_offset: Some(header_offset),
4063 }
4064 }
4065 pub fn push_alloc_fast(mut self, value: u32) -> Self {
4066 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4067 self.as_rec_mut().extend(value.to_ne_bytes());
4068 self
4069 }
4070 pub fn push_alloc_slow(mut self, value: u32) -> Self {
4071 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4072 self.as_rec_mut().extend(value.to_ne_bytes());
4073 self
4074 }
4075 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
4076 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4077 self.as_rec_mut().extend(value.to_ne_bytes());
4078 self
4079 }
4080 pub fn push_alloc_empty(mut self, value: u32) -> Self {
4081 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4082 self.as_rec_mut().extend(value.to_ne_bytes());
4083 self
4084 }
4085 pub fn push_alloc_refill(mut self, value: u32) -> Self {
4086 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4087 self.as_rec_mut().extend(value.to_ne_bytes());
4088 self
4089 }
4090 pub fn push_alloc_waive(mut self, value: u32) -> Self {
4091 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4092 self.as_rec_mut().extend(value.to_ne_bytes());
4093 self
4094 }
4095 pub fn push_recycle_cached(mut self, value: u32) -> Self {
4096 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4097 self.as_rec_mut().extend(value.to_ne_bytes());
4098 self
4099 }
4100 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
4101 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4102 self.as_rec_mut().extend(value.to_ne_bytes());
4103 self
4104 }
4105 pub fn push_recycle_ring(mut self, value: u32) -> Self {
4106 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4107 self.as_rec_mut().extend(value.to_ne_bytes());
4108 self
4109 }
4110 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
4111 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4112 self.as_rec_mut().extend(value.to_ne_bytes());
4113 self
4114 }
4115 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
4116 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4117 self.as_rec_mut().extend(value.to_ne_bytes());
4118 self
4119 }
4120}
4121impl<Prev: Rec> Drop for PushPagePoolStats<Prev> {
4122 fn drop(&mut self) {
4123 if let Some(prev) = &mut self.prev {
4124 if let Some(header_offset) = &self.header_offset {
4125 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4126 }
4127 }
4128 }
4129}
4130pub struct PushNapi<Prev: Rec> {
4131 pub(crate) prev: Option<Prev>,
4132 pub(crate) header_offset: Option<usize>,
4133}
4134impl<Prev: Rec> Rec for PushNapi<Prev> {
4135 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4136 self.prev.as_mut().unwrap().as_rec_mut()
4137 }
4138 fn as_rec(&self) -> &Vec<u8> {
4139 self.prev.as_ref().unwrap().as_rec()
4140 }
4141}
4142impl<Prev: Rec> PushNapi<Prev> {
4143 pub fn new(prev: Prev) -> Self {
4144 Self {
4145 prev: Some(prev),
4146 header_offset: None,
4147 }
4148 }
4149 pub fn end_nested(mut self) -> Prev {
4150 let mut prev = self.prev.take().unwrap();
4151 if let Some(header_offset) = &self.header_offset {
4152 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4153 }
4154 prev
4155 }
4156 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
4157 pub fn push_ifindex(mut self, value: u32) -> Self {
4158 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4159 self.as_rec_mut().extend(value.to_ne_bytes());
4160 self
4161 }
4162 #[doc = "ID of the NAPI instance."]
4163 pub fn push_id(mut self, value: u32) -> Self {
4164 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4165 self.as_rec_mut().extend(value.to_ne_bytes());
4166 self
4167 }
4168 #[doc = "The associated interrupt vector number for the napi"]
4169 pub fn push_irq(mut self, value: u32) -> Self {
4170 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4171 self.as_rec_mut().extend(value.to_ne_bytes());
4172 self
4173 }
4174 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
4175 pub fn push_pid(mut self, value: u32) -> Self {
4176 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4177 self.as_rec_mut().extend(value.to_ne_bytes());
4178 self
4179 }
4180 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
4181 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
4182 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4183 self.as_rec_mut().extend(value.to_ne_bytes());
4184 self
4185 }
4186 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
4187 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
4188 push_header(self.as_rec_mut(), 6u16, 4 as u16);
4189 self.as_rec_mut().extend(value.to_ne_bytes());
4190 self
4191 }
4192 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
4193 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
4194 push_header(self.as_rec_mut(), 7u16, 4 as u16);
4195 self.as_rec_mut().extend(value.to_ne_bytes());
4196 self
4197 }
4198 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
4199 pub fn push_threaded(mut self, value: u32) -> Self {
4200 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4201 self.as_rec_mut().extend(value.to_ne_bytes());
4202 self
4203 }
4204}
4205impl<Prev: Rec> Drop for PushNapi<Prev> {
4206 fn drop(&mut self) {
4207 if let Some(prev) = &mut self.prev {
4208 if let Some(header_offset) = &self.header_offset {
4209 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4210 }
4211 }
4212 }
4213}
4214pub struct PushXskInfo<Prev: Rec> {
4215 pub(crate) prev: Option<Prev>,
4216 pub(crate) header_offset: Option<usize>,
4217}
4218impl<Prev: Rec> Rec for PushXskInfo<Prev> {
4219 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4220 self.prev.as_mut().unwrap().as_rec_mut()
4221 }
4222 fn as_rec(&self) -> &Vec<u8> {
4223 self.prev.as_ref().unwrap().as_rec()
4224 }
4225}
4226impl<Prev: Rec> PushXskInfo<Prev> {
4227 pub fn new(prev: Prev) -> Self {
4228 Self {
4229 prev: Some(prev),
4230 header_offset: None,
4231 }
4232 }
4233 pub fn end_nested(mut self) -> Prev {
4234 let mut prev = self.prev.take().unwrap();
4235 if let Some(header_offset) = &self.header_offset {
4236 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4237 }
4238 prev
4239 }
4240}
4241impl<Prev: Rec> Drop for PushXskInfo<Prev> {
4242 fn drop(&mut self) {
4243 if let Some(prev) = &mut self.prev {
4244 if let Some(header_offset) = &self.header_offset {
4245 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4246 }
4247 }
4248 }
4249}
4250pub struct PushQueue<Prev: Rec> {
4251 pub(crate) prev: Option<Prev>,
4252 pub(crate) header_offset: Option<usize>,
4253}
4254impl<Prev: Rec> Rec for PushQueue<Prev> {
4255 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4256 self.prev.as_mut().unwrap().as_rec_mut()
4257 }
4258 fn as_rec(&self) -> &Vec<u8> {
4259 self.prev.as_ref().unwrap().as_rec()
4260 }
4261}
4262impl<Prev: Rec> PushQueue<Prev> {
4263 pub fn new(prev: Prev) -> Self {
4264 Self {
4265 prev: Some(prev),
4266 header_offset: None,
4267 }
4268 }
4269 pub fn end_nested(mut self) -> Prev {
4270 let mut prev = self.prev.take().unwrap();
4271 if let Some(header_offset) = &self.header_offset {
4272 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4273 }
4274 prev
4275 }
4276 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
4277 pub fn push_id(mut self, value: u32) -> Self {
4278 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4279 self.as_rec_mut().extend(value.to_ne_bytes());
4280 self
4281 }
4282 #[doc = "ifindex of the netdevice to which the queue belongs."]
4283 pub fn push_ifindex(mut self, value: u32) -> Self {
4284 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4285 self.as_rec_mut().extend(value.to_ne_bytes());
4286 self
4287 }
4288 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
4289 pub fn push_type(mut self, value: u32) -> Self {
4290 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4291 self.as_rec_mut().extend(value.to_ne_bytes());
4292 self
4293 }
4294 #[doc = "ID of the NAPI instance which services this queue."]
4295 pub fn push_napi_id(mut self, value: u32) -> Self {
4296 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4297 self.as_rec_mut().extend(value.to_ne_bytes());
4298 self
4299 }
4300 #[doc = "ID of the dmabuf attached to this queue, if any."]
4301 pub fn push_dmabuf(mut self, value: u32) -> Self {
4302 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4303 self.as_rec_mut().extend(value.to_ne_bytes());
4304 self
4305 }
4306 #[doc = "io_uring memory provider information."]
4307 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4308 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
4309 PushIoUringProviderInfo {
4310 prev: Some(self),
4311 header_offset: Some(header_offset),
4312 }
4313 }
4314 #[doc = "XSK information for this queue, if any."]
4315 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
4316 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
4317 PushXskInfo {
4318 prev: Some(self),
4319 header_offset: Some(header_offset),
4320 }
4321 }
4322}
4323impl<Prev: Rec> Drop for PushQueue<Prev> {
4324 fn drop(&mut self) {
4325 if let Some(prev) = &mut self.prev {
4326 if let Some(header_offset) = &self.header_offset {
4327 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4328 }
4329 }
4330 }
4331}
4332pub struct PushQstats<Prev: Rec> {
4333 pub(crate) prev: Option<Prev>,
4334 pub(crate) header_offset: Option<usize>,
4335}
4336impl<Prev: Rec> Rec for PushQstats<Prev> {
4337 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4338 self.prev.as_mut().unwrap().as_rec_mut()
4339 }
4340 fn as_rec(&self) -> &Vec<u8> {
4341 self.prev.as_ref().unwrap().as_rec()
4342 }
4343}
4344impl<Prev: Rec> PushQstats<Prev> {
4345 pub fn new(prev: Prev) -> Self {
4346 Self {
4347 prev: Some(prev),
4348 header_offset: None,
4349 }
4350 }
4351 pub fn end_nested(mut self) -> Prev {
4352 let mut prev = self.prev.take().unwrap();
4353 if let Some(header_offset) = &self.header_offset {
4354 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4355 }
4356 prev
4357 }
4358 #[doc = "ifindex of the netdevice to which stats belong."]
4359 pub fn push_ifindex(mut self, value: u32) -> Self {
4360 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4361 self.as_rec_mut().extend(value.to_ne_bytes());
4362 self
4363 }
4364 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
4365 pub fn push_queue_type(mut self, value: u32) -> Self {
4366 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4367 self.as_rec_mut().extend(value.to_ne_bytes());
4368 self
4369 }
4370 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
4371 pub fn push_queue_id(mut self, value: u32) -> Self {
4372 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4373 self.as_rec_mut().extend(value.to_ne_bytes());
4374 self
4375 }
4376 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
4377 pub fn push_scope(mut self, value: u32) -> Self {
4378 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4379 self.as_rec_mut().extend(value.to_ne_bytes());
4380 self
4381 }
4382 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
4383 pub fn push_rx_packets(mut self, value: u32) -> Self {
4384 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4385 self.as_rec_mut().extend(value.to_ne_bytes());
4386 self
4387 }
4388 #[doc = "Successfully received bytes, see `rx-packets`."]
4389 pub fn push_rx_bytes(mut self, value: u32) -> Self {
4390 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4391 self.as_rec_mut().extend(value.to_ne_bytes());
4392 self
4393 }
4394 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
4395 pub fn push_tx_packets(mut self, value: u32) -> Self {
4396 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4397 self.as_rec_mut().extend(value.to_ne_bytes());
4398 self
4399 }
4400 #[doc = "Successfully sent bytes, see `tx-packets`."]
4401 pub fn push_tx_bytes(mut self, value: u32) -> Self {
4402 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4403 self.as_rec_mut().extend(value.to_ne_bytes());
4404 self
4405 }
4406 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
4407 pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
4408 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4409 self.as_rec_mut().extend(value.to_ne_bytes());
4410 self
4411 }
4412 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
4413 pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
4414 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4415 self.as_rec_mut().extend(value.to_ne_bytes());
4416 self
4417 }
4418 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
4419 pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
4420 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4421 self.as_rec_mut().extend(value.to_ne_bytes());
4422 self
4423 }
4424 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
4425 pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
4426 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4427 self.as_rec_mut().extend(value.to_ne_bytes());
4428 self
4429 }
4430 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
4431 pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
4432 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4433 self.as_rec_mut().extend(value.to_ne_bytes());
4434 self
4435 }
4436 #[doc = "Number of packets that were not checksummed by device."]
4437 pub fn push_rx_csum_none(mut self, value: u32) -> Self {
4438 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4439 self.as_rec_mut().extend(value.to_ne_bytes());
4440 self
4441 }
4442 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
4443 pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
4444 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4445 self.as_rec_mut().extend(value.to_ne_bytes());
4446 self
4447 }
4448 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
4449 pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
4450 push_header(self.as_rec_mut(), 19u16, 4 as u16);
4451 self.as_rec_mut().extend(value.to_ne_bytes());
4452 self
4453 }
4454 #[doc = "See `rx-hw-gro-packets`."]
4455 pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
4456 push_header(self.as_rec_mut(), 20u16, 4 as u16);
4457 self.as_rec_mut().extend(value.to_ne_bytes());
4458 self
4459 }
4460 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
4461 pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
4462 push_header(self.as_rec_mut(), 21u16, 4 as u16);
4463 self.as_rec_mut().extend(value.to_ne_bytes());
4464 self
4465 }
4466 #[doc = "See `rx-hw-gro-wire-packets`."]
4467 pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
4468 push_header(self.as_rec_mut(), 22u16, 4 as u16);
4469 self.as_rec_mut().extend(value.to_ne_bytes());
4470 self
4471 }
4472 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
4473 pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4474 push_header(self.as_rec_mut(), 23u16, 4 as u16);
4475 self.as_rec_mut().extend(value.to_ne_bytes());
4476 self
4477 }
4478 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
4479 pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
4480 push_header(self.as_rec_mut(), 24u16, 4 as u16);
4481 self.as_rec_mut().extend(value.to_ne_bytes());
4482 self
4483 }
4484 #[doc = "Number of packets dropped because they were invalid or malformed."]
4485 pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
4486 push_header(self.as_rec_mut(), 25u16, 4 as u16);
4487 self.as_rec_mut().extend(value.to_ne_bytes());
4488 self
4489 }
4490 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
4491 pub fn push_tx_csum_none(mut self, value: u32) -> Self {
4492 push_header(self.as_rec_mut(), 26u16, 4 as u16);
4493 self.as_rec_mut().extend(value.to_ne_bytes());
4494 self
4495 }
4496 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
4497 pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
4498 push_header(self.as_rec_mut(), 27u16, 4 as u16);
4499 self.as_rec_mut().extend(value.to_ne_bytes());
4500 self
4501 }
4502 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
4503 pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
4504 push_header(self.as_rec_mut(), 28u16, 4 as u16);
4505 self.as_rec_mut().extend(value.to_ne_bytes());
4506 self
4507 }
4508 #[doc = "See `tx-hw-gso-packets`."]
4509 pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
4510 push_header(self.as_rec_mut(), 29u16, 4 as u16);
4511 self.as_rec_mut().extend(value.to_ne_bytes());
4512 self
4513 }
4514 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
4515 pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
4516 push_header(self.as_rec_mut(), 30u16, 4 as u16);
4517 self.as_rec_mut().extend(value.to_ne_bytes());
4518 self
4519 }
4520 #[doc = "See `tx-hw-gso-wire-packets`."]
4521 pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
4522 push_header(self.as_rec_mut(), 31u16, 4 as u16);
4523 self.as_rec_mut().extend(value.to_ne_bytes());
4524 self
4525 }
4526 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
4527 pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4528 push_header(self.as_rec_mut(), 32u16, 4 as u16);
4529 self.as_rec_mut().extend(value.to_ne_bytes());
4530 self
4531 }
4532 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
4533 pub fn push_tx_stop(mut self, value: u32) -> Self {
4534 push_header(self.as_rec_mut(), 33u16, 4 as u16);
4535 self.as_rec_mut().extend(value.to_ne_bytes());
4536 self
4537 }
4538 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
4539 pub fn push_tx_wake(mut self, value: u32) -> Self {
4540 push_header(self.as_rec_mut(), 34u16, 4 as u16);
4541 self.as_rec_mut().extend(value.to_ne_bytes());
4542 self
4543 }
4544}
4545impl<Prev: Rec> Drop for PushQstats<Prev> {
4546 fn drop(&mut self) {
4547 if let Some(prev) = &mut self.prev {
4548 if let Some(header_offset) = &self.header_offset {
4549 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4550 }
4551 }
4552 }
4553}
4554pub struct PushQueueId<Prev: Rec> {
4555 pub(crate) prev: Option<Prev>,
4556 pub(crate) header_offset: Option<usize>,
4557}
4558impl<Prev: Rec> Rec for PushQueueId<Prev> {
4559 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4560 self.prev.as_mut().unwrap().as_rec_mut()
4561 }
4562 fn as_rec(&self) -> &Vec<u8> {
4563 self.prev.as_ref().unwrap().as_rec()
4564 }
4565}
4566impl<Prev: Rec> PushQueueId<Prev> {
4567 pub fn new(prev: Prev) -> Self {
4568 Self {
4569 prev: Some(prev),
4570 header_offset: None,
4571 }
4572 }
4573 pub fn end_nested(mut self) -> Prev {
4574 let mut prev = self.prev.take().unwrap();
4575 if let Some(header_offset) = &self.header_offset {
4576 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4577 }
4578 prev
4579 }
4580 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
4581 pub fn push_id(mut self, value: u32) -> Self {
4582 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4583 self.as_rec_mut().extend(value.to_ne_bytes());
4584 self
4585 }
4586 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
4587 pub fn push_type(mut self, value: u32) -> Self {
4588 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4589 self.as_rec_mut().extend(value.to_ne_bytes());
4590 self
4591 }
4592}
4593impl<Prev: Rec> Drop for PushQueueId<Prev> {
4594 fn drop(&mut self) {
4595 if let Some(prev) = &mut self.prev {
4596 if let Some(header_offset) = &self.header_offset {
4597 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4598 }
4599 }
4600 }
4601}
4602pub struct PushDmabuf<Prev: Rec> {
4603 pub(crate) prev: Option<Prev>,
4604 pub(crate) header_offset: Option<usize>,
4605}
4606impl<Prev: Rec> Rec for PushDmabuf<Prev> {
4607 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4608 self.prev.as_mut().unwrap().as_rec_mut()
4609 }
4610 fn as_rec(&self) -> &Vec<u8> {
4611 self.prev.as_ref().unwrap().as_rec()
4612 }
4613}
4614impl<Prev: Rec> PushDmabuf<Prev> {
4615 pub fn new(prev: Prev) -> Self {
4616 Self {
4617 prev: Some(prev),
4618 header_offset: None,
4619 }
4620 }
4621 pub fn end_nested(mut self) -> Prev {
4622 let mut prev = self.prev.take().unwrap();
4623 if let Some(header_offset) = &self.header_offset {
4624 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4625 }
4626 prev
4627 }
4628 #[doc = "netdev ifindex to bind the dmabuf to."]
4629 pub fn push_ifindex(mut self, value: u32) -> Self {
4630 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4631 self.as_rec_mut().extend(value.to_ne_bytes());
4632 self
4633 }
4634 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
4635 pub fn nested_queues(mut self) -> PushQueueId<Self> {
4636 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4637 PushQueueId {
4638 prev: Some(self),
4639 header_offset: Some(header_offset),
4640 }
4641 }
4642 #[doc = "dmabuf file descriptor to bind."]
4643 pub fn push_fd(mut self, value: u32) -> Self {
4644 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4645 self.as_rec_mut().extend(value.to_ne_bytes());
4646 self
4647 }
4648 #[doc = "id of the dmabuf binding"]
4649 pub fn push_id(mut self, value: u32) -> Self {
4650 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4651 self.as_rec_mut().extend(value.to_ne_bytes());
4652 self
4653 }
4654}
4655impl<Prev: Rec> Drop for PushDmabuf<Prev> {
4656 fn drop(&mut self) {
4657 if let Some(prev) = &mut self.prev {
4658 if let Some(header_offset) = &self.header_offset {
4659 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4660 }
4661 }
4662 }
4663}
4664#[doc = "Get / dump information about a netdev."]
4665pub struct PushOpDevGetDumpRequest<Prev: Rec> {
4666 pub(crate) prev: Option<Prev>,
4667 pub(crate) header_offset: Option<usize>,
4668}
4669impl<Prev: Rec> Rec for PushOpDevGetDumpRequest<Prev> {
4670 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4671 self.prev.as_mut().unwrap().as_rec_mut()
4672 }
4673 fn as_rec(&self) -> &Vec<u8> {
4674 self.prev.as_ref().unwrap().as_rec()
4675 }
4676}
4677impl<Prev: Rec> PushOpDevGetDumpRequest<Prev> {
4678 pub fn new(mut prev: Prev) -> Self {
4679 Self::write_header(&mut prev);
4680 Self::new_without_header(prev)
4681 }
4682 fn new_without_header(prev: Prev) -> Self {
4683 Self {
4684 prev: Some(prev),
4685 header_offset: None,
4686 }
4687 }
4688 fn write_header(prev: &mut Prev) {
4689 let mut header = PushBuiltinNfgenmsg::new();
4690 header.set_cmd(1u8);
4691 header.set_version(1u8);
4692 prev.as_rec_mut().extend(header.as_slice());
4693 }
4694 pub fn end_nested(mut self) -> Prev {
4695 let mut prev = self.prev.take().unwrap();
4696 if let Some(header_offset) = &self.header_offset {
4697 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4698 }
4699 prev
4700 }
4701}
4702impl<Prev: Rec> Drop for PushOpDevGetDumpRequest<Prev> {
4703 fn drop(&mut self) {
4704 if let Some(prev) = &mut self.prev {
4705 if let Some(header_offset) = &self.header_offset {
4706 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4707 }
4708 }
4709 }
4710}
4711#[doc = "Get / dump information about a netdev."]
4712#[derive(Clone)]
4713pub enum OpDevGetDumpRequest {}
4714impl<'a> IterableOpDevGetDumpRequest<'a> {}
4715impl OpDevGetDumpRequest {
4716 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpRequest<'a> {
4717 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4718 IterableOpDevGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
4719 }
4720 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4721 Dev::attr_from_type(r#type)
4722 }
4723}
4724#[derive(Clone, Copy, Default)]
4725pub struct IterableOpDevGetDumpRequest<'a> {
4726 buf: &'a [u8],
4727 pos: usize,
4728 orig_loc: usize,
4729}
4730impl<'a> IterableOpDevGetDumpRequest<'a> {
4731 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4732 Self {
4733 buf,
4734 pos: 0,
4735 orig_loc,
4736 }
4737 }
4738 pub fn get_buf(&self) -> &'a [u8] {
4739 self.buf
4740 }
4741}
4742impl<'a> Iterator for IterableOpDevGetDumpRequest<'a> {
4743 type Item = Result<OpDevGetDumpRequest, ErrorContext>;
4744 fn next(&mut self) -> Option<Self::Item> {
4745 let pos = self.pos;
4746 let mut r#type;
4747 loop {
4748 r#type = None;
4749 if self.buf.len() == self.pos {
4750 return None;
4751 }
4752 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
4753 break;
4754 };
4755 r#type = Some(header.r#type);
4756 let res = match header.r#type {
4757 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
4758 n => continue,
4759 };
4760 return Some(Ok(res));
4761 }
4762 Some(Err(ErrorContext::new(
4763 "OpDevGetDumpRequest",
4764 r#type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4765 self.orig_loc,
4766 self.buf.as_ptr().wrapping_add(pos) as usize,
4767 )))
4768 }
4769}
4770impl std::fmt::Debug for IterableOpDevGetDumpRequest<'_> {
4771 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4772 let mut fmt = f.debug_struct("OpDevGetDumpRequest");
4773 for attr in self.clone() {
4774 let attr = match attr {
4775 Ok(a) => a,
4776 Err(err) => {
4777 fmt.finish()?;
4778 f.write_str("Err(")?;
4779 err.fmt(f)?;
4780 return f.write_str(")");
4781 }
4782 };
4783 match attr {};
4784 }
4785 fmt.finish()
4786 }
4787}
4788impl IterableOpDevGetDumpRequest<'_> {
4789 pub fn lookup_attr(
4790 &self,
4791 offset: usize,
4792 missing_type: Option<u16>,
4793 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4794 let mut stack = Vec::new();
4795 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4796 if cur == offset + PushBuiltinNfgenmsg::len() {
4797 stack.push(("OpDevGetDumpRequest", offset));
4798 return (
4799 stack,
4800 missing_type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4801 );
4802 }
4803 (stack, None)
4804 }
4805}
4806#[doc = "Get / dump information about a netdev."]
4807pub struct PushOpDevGetDumpReply<Prev: Rec> {
4808 pub(crate) prev: Option<Prev>,
4809 pub(crate) header_offset: Option<usize>,
4810}
4811impl<Prev: Rec> Rec for PushOpDevGetDumpReply<Prev> {
4812 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4813 self.prev.as_mut().unwrap().as_rec_mut()
4814 }
4815 fn as_rec(&self) -> &Vec<u8> {
4816 self.prev.as_ref().unwrap().as_rec()
4817 }
4818}
4819impl<Prev: Rec> PushOpDevGetDumpReply<Prev> {
4820 pub fn new(mut prev: Prev) -> Self {
4821 Self::write_header(&mut prev);
4822 Self::new_without_header(prev)
4823 }
4824 fn new_without_header(prev: Prev) -> Self {
4825 Self {
4826 prev: Some(prev),
4827 header_offset: None,
4828 }
4829 }
4830 fn write_header(prev: &mut Prev) {
4831 let mut header = PushBuiltinNfgenmsg::new();
4832 header.set_cmd(1u8);
4833 header.set_version(1u8);
4834 prev.as_rec_mut().extend(header.as_slice());
4835 }
4836 pub fn end_nested(mut self) -> Prev {
4837 let mut prev = self.prev.take().unwrap();
4838 if let Some(header_offset) = &self.header_offset {
4839 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4840 }
4841 prev
4842 }
4843 #[doc = "netdev ifindex"]
4844 pub fn push_ifindex(mut self, value: u32) -> Self {
4845 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4846 self.as_rec_mut().extend(value.to_ne_bytes());
4847 self
4848 }
4849 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4850 pub fn push_xdp_features(mut self, value: u64) -> Self {
4851 push_header(self.as_rec_mut(), 3u16, 8 as u16);
4852 self.as_rec_mut().extend(value.to_ne_bytes());
4853 self
4854 }
4855 #[doc = "max fragment count supported by ZC driver"]
4856 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
4857 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4858 self.as_rec_mut().extend(value.to_ne_bytes());
4859 self
4860 }
4861 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4862 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
4863 push_header(self.as_rec_mut(), 5u16, 8 as u16);
4864 self.as_rec_mut().extend(value.to_ne_bytes());
4865 self
4866 }
4867 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4868 pub fn push_xsk_features(mut self, value: u64) -> Self {
4869 push_header(self.as_rec_mut(), 6u16, 8 as u16);
4870 self.as_rec_mut().extend(value.to_ne_bytes());
4871 self
4872 }
4873}
4874impl<Prev: Rec> Drop for PushOpDevGetDumpReply<Prev> {
4875 fn drop(&mut self) {
4876 if let Some(prev) = &mut self.prev {
4877 if let Some(header_offset) = &self.header_offset {
4878 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4879 }
4880 }
4881 }
4882}
4883#[doc = "Get / dump information about a netdev."]
4884#[derive(Clone)]
4885pub enum OpDevGetDumpReply {
4886 #[doc = "netdev ifindex"]
4887 Ifindex(u32),
4888 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4889 XdpFeatures(u64),
4890 #[doc = "max fragment count supported by ZC driver"]
4891 XdpZcMaxSegs(u32),
4892 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4893 XdpRxMetadataFeatures(u64),
4894 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4895 XskFeatures(u64),
4896}
4897impl<'a> IterableOpDevGetDumpReply<'a> {
4898 #[doc = "netdev ifindex"]
4899 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
4900 let mut iter = self.clone();
4901 iter.pos = 0;
4902 for attr in iter {
4903 if let OpDevGetDumpReply::Ifindex(val) = attr? {
4904 return Ok(val);
4905 }
4906 }
4907 Err(ErrorContext::new_missing(
4908 "OpDevGetDumpReply",
4909 "Ifindex",
4910 self.orig_loc,
4911 self.buf.as_ptr() as usize,
4912 ))
4913 }
4914 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4915 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
4916 let mut iter = self.clone();
4917 iter.pos = 0;
4918 for attr in iter {
4919 if let OpDevGetDumpReply::XdpFeatures(val) = attr? {
4920 return Ok(val);
4921 }
4922 }
4923 Err(ErrorContext::new_missing(
4924 "OpDevGetDumpReply",
4925 "XdpFeatures",
4926 self.orig_loc,
4927 self.buf.as_ptr() as usize,
4928 ))
4929 }
4930 #[doc = "max fragment count supported by ZC driver"]
4931 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
4932 let mut iter = self.clone();
4933 iter.pos = 0;
4934 for attr in iter {
4935 if let OpDevGetDumpReply::XdpZcMaxSegs(val) = attr? {
4936 return Ok(val);
4937 }
4938 }
4939 Err(ErrorContext::new_missing(
4940 "OpDevGetDumpReply",
4941 "XdpZcMaxSegs",
4942 self.orig_loc,
4943 self.buf.as_ptr() as usize,
4944 ))
4945 }
4946 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4947 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
4948 let mut iter = self.clone();
4949 iter.pos = 0;
4950 for attr in iter {
4951 if let OpDevGetDumpReply::XdpRxMetadataFeatures(val) = attr? {
4952 return Ok(val);
4953 }
4954 }
4955 Err(ErrorContext::new_missing(
4956 "OpDevGetDumpReply",
4957 "XdpRxMetadataFeatures",
4958 self.orig_loc,
4959 self.buf.as_ptr() as usize,
4960 ))
4961 }
4962 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4963 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
4964 let mut iter = self.clone();
4965 iter.pos = 0;
4966 for attr in iter {
4967 if let OpDevGetDumpReply::XskFeatures(val) = attr? {
4968 return Ok(val);
4969 }
4970 }
4971 Err(ErrorContext::new_missing(
4972 "OpDevGetDumpReply",
4973 "XskFeatures",
4974 self.orig_loc,
4975 self.buf.as_ptr() as usize,
4976 ))
4977 }
4978}
4979impl OpDevGetDumpReply {
4980 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpReply<'a> {
4981 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4982 IterableOpDevGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
4983 }
4984 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4985 Dev::attr_from_type(r#type)
4986 }
4987}
4988#[derive(Clone, Copy, Default)]
4989pub struct IterableOpDevGetDumpReply<'a> {
4990 buf: &'a [u8],
4991 pos: usize,
4992 orig_loc: usize,
4993}
4994impl<'a> IterableOpDevGetDumpReply<'a> {
4995 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4996 Self {
4997 buf,
4998 pos: 0,
4999 orig_loc,
5000 }
5001 }
5002 pub fn get_buf(&self) -> &'a [u8] {
5003 self.buf
5004 }
5005}
5006impl<'a> Iterator for IterableOpDevGetDumpReply<'a> {
5007 type Item = Result<OpDevGetDumpReply, ErrorContext>;
5008 fn next(&mut self) -> Option<Self::Item> {
5009 let pos = self.pos;
5010 let mut r#type;
5011 loop {
5012 r#type = None;
5013 if self.buf.len() == self.pos {
5014 return None;
5015 }
5016 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5017 break;
5018 };
5019 r#type = Some(header.r#type);
5020 let res = match header.r#type {
5021 1u16 => OpDevGetDumpReply::Ifindex({
5022 let res = parse_u32(next);
5023 let Some(val) = res else { break };
5024 val
5025 }),
5026 3u16 => OpDevGetDumpReply::XdpFeatures({
5027 let res = parse_u64(next);
5028 let Some(val) = res else { break };
5029 val
5030 }),
5031 4u16 => OpDevGetDumpReply::XdpZcMaxSegs({
5032 let res = parse_u32(next);
5033 let Some(val) = res else { break };
5034 val
5035 }),
5036 5u16 => OpDevGetDumpReply::XdpRxMetadataFeatures({
5037 let res = parse_u64(next);
5038 let Some(val) = res else { break };
5039 val
5040 }),
5041 6u16 => OpDevGetDumpReply::XskFeatures({
5042 let res = parse_u64(next);
5043 let Some(val) = res else { break };
5044 val
5045 }),
5046 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5047 n => continue,
5048 };
5049 return Some(Ok(res));
5050 }
5051 Some(Err(ErrorContext::new(
5052 "OpDevGetDumpReply",
5053 r#type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5054 self.orig_loc,
5055 self.buf.as_ptr().wrapping_add(pos) as usize,
5056 )))
5057 }
5058}
5059impl std::fmt::Debug for IterableOpDevGetDumpReply<'_> {
5060 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5061 let mut fmt = f.debug_struct("OpDevGetDumpReply");
5062 for attr in self.clone() {
5063 let attr = match attr {
5064 Ok(a) => a,
5065 Err(err) => {
5066 fmt.finish()?;
5067 f.write_str("Err(")?;
5068 err.fmt(f)?;
5069 return f.write_str(")");
5070 }
5071 };
5072 match attr {
5073 OpDevGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
5074 OpDevGetDumpReply::XdpFeatures(val) => {
5075 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5076 }
5077 OpDevGetDumpReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5078 OpDevGetDumpReply::XdpRxMetadataFeatures(val) => fmt.field(
5079 "XdpRxMetadataFeatures",
5080 &FormatFlags(val.into(), XdpRxMetadata::from_value),
5081 ),
5082 OpDevGetDumpReply::XskFeatures(val) => fmt.field(
5083 "XskFeatures",
5084 &FormatFlags(val.into(), XskFlags::from_value),
5085 ),
5086 };
5087 }
5088 fmt.finish()
5089 }
5090}
5091impl IterableOpDevGetDumpReply<'_> {
5092 pub fn lookup_attr(
5093 &self,
5094 offset: usize,
5095 missing_type: Option<u16>,
5096 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5097 let mut stack = Vec::new();
5098 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5099 if cur == offset + PushBuiltinNfgenmsg::len() {
5100 stack.push(("OpDevGetDumpReply", offset));
5101 return (
5102 stack,
5103 missing_type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5104 );
5105 }
5106 if cur > offset || cur + self.buf.len() < offset {
5107 return (stack, None);
5108 }
5109 let mut attrs = self.clone();
5110 let mut last_off = cur + attrs.pos;
5111 while let Some(attr) = attrs.next() {
5112 let Ok(attr) = attr else { break };
5113 match attr {
5114 OpDevGetDumpReply::Ifindex(val) => {
5115 if last_off == offset {
5116 stack.push(("Ifindex", last_off));
5117 break;
5118 }
5119 }
5120 OpDevGetDumpReply::XdpFeatures(val) => {
5121 if last_off == offset {
5122 stack.push(("XdpFeatures", last_off));
5123 break;
5124 }
5125 }
5126 OpDevGetDumpReply::XdpZcMaxSegs(val) => {
5127 if last_off == offset {
5128 stack.push(("XdpZcMaxSegs", last_off));
5129 break;
5130 }
5131 }
5132 OpDevGetDumpReply::XdpRxMetadataFeatures(val) => {
5133 if last_off == offset {
5134 stack.push(("XdpRxMetadataFeatures", last_off));
5135 break;
5136 }
5137 }
5138 OpDevGetDumpReply::XskFeatures(val) => {
5139 if last_off == offset {
5140 stack.push(("XskFeatures", last_off));
5141 break;
5142 }
5143 }
5144 _ => {}
5145 };
5146 last_off = cur + attrs.pos;
5147 }
5148 if !stack.is_empty() {
5149 stack.push(("OpDevGetDumpReply", cur));
5150 }
5151 (stack, None)
5152 }
5153}
5154#[derive(Debug)]
5155pub struct RequestOpDevGetDumpRequest<'r> {
5156 request: Request<'r>,
5157}
5158impl<'r> RequestOpDevGetDumpRequest<'r> {
5159 pub fn new(mut request: Request<'r>) -> Self {
5160 PushOpDevGetDumpRequest::write_header(&mut request.buf_mut());
5161 Self {
5162 request: request.set_dump(),
5163 }
5164 }
5165 pub fn encode(&mut self) -> PushOpDevGetDumpRequest<&mut Vec<u8>> {
5166 PushOpDevGetDumpRequest::new_without_header(self.request.buf_mut())
5167 }
5168 pub fn into_encoder(self) -> PushOpDevGetDumpRequest<RequestBuf<'r>> {
5169 PushOpDevGetDumpRequest::new_without_header(self.request.buf)
5170 }
5171 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpDevGetDumpRequest<'buf> {
5172 OpDevGetDumpRequest::new(buf)
5173 }
5174}
5175impl NetlinkRequest for RequestOpDevGetDumpRequest<'_> {
5176 fn protocol(&self) -> Protocol {
5177 Protocol::Generic("netdev".as_bytes())
5178 }
5179 fn flags(&self) -> u16 {
5180 self.request.flags
5181 }
5182 fn payload(&self) -> &[u8] {
5183 self.request.buf()
5184 }
5185 type ReplyType<'buf> = IterableOpDevGetDumpReply<'buf>;
5186 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5187 OpDevGetDumpReply::new(buf)
5188 }
5189 fn lookup(
5190 buf: &[u8],
5191 offset: usize,
5192 missing_type: Option<u16>,
5193 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5194 OpDevGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
5195 }
5196}
5197#[doc = "Get / dump information about a netdev."]
5198pub struct PushOpDevGetDoRequest<Prev: Rec> {
5199 pub(crate) prev: Option<Prev>,
5200 pub(crate) header_offset: Option<usize>,
5201}
5202impl<Prev: Rec> Rec for PushOpDevGetDoRequest<Prev> {
5203 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5204 self.prev.as_mut().unwrap().as_rec_mut()
5205 }
5206 fn as_rec(&self) -> &Vec<u8> {
5207 self.prev.as_ref().unwrap().as_rec()
5208 }
5209}
5210impl<Prev: Rec> PushOpDevGetDoRequest<Prev> {
5211 pub fn new(mut prev: Prev) -> Self {
5212 Self::write_header(&mut prev);
5213 Self::new_without_header(prev)
5214 }
5215 fn new_without_header(prev: Prev) -> Self {
5216 Self {
5217 prev: Some(prev),
5218 header_offset: None,
5219 }
5220 }
5221 fn write_header(prev: &mut Prev) {
5222 let mut header = PushBuiltinNfgenmsg::new();
5223 header.set_cmd(1u8);
5224 header.set_version(1u8);
5225 prev.as_rec_mut().extend(header.as_slice());
5226 }
5227 pub fn end_nested(mut self) -> Prev {
5228 let mut prev = self.prev.take().unwrap();
5229 if let Some(header_offset) = &self.header_offset {
5230 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5231 }
5232 prev
5233 }
5234 #[doc = "netdev ifindex"]
5235 pub fn push_ifindex(mut self, value: u32) -> Self {
5236 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5237 self.as_rec_mut().extend(value.to_ne_bytes());
5238 self
5239 }
5240}
5241impl<Prev: Rec> Drop for PushOpDevGetDoRequest<Prev> {
5242 fn drop(&mut self) {
5243 if let Some(prev) = &mut self.prev {
5244 if let Some(header_offset) = &self.header_offset {
5245 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5246 }
5247 }
5248 }
5249}
5250#[doc = "Get / dump information about a netdev."]
5251#[derive(Clone)]
5252pub enum OpDevGetDoRequest {
5253 #[doc = "netdev ifindex"]
5254 Ifindex(u32),
5255}
5256impl<'a> IterableOpDevGetDoRequest<'a> {
5257 #[doc = "netdev ifindex"]
5258 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5259 let mut iter = self.clone();
5260 iter.pos = 0;
5261 for attr in iter {
5262 if let OpDevGetDoRequest::Ifindex(val) = attr? {
5263 return Ok(val);
5264 }
5265 }
5266 Err(ErrorContext::new_missing(
5267 "OpDevGetDoRequest",
5268 "Ifindex",
5269 self.orig_loc,
5270 self.buf.as_ptr() as usize,
5271 ))
5272 }
5273}
5274impl OpDevGetDoRequest {
5275 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoRequest<'a> {
5276 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5277 IterableOpDevGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
5278 }
5279 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5280 Dev::attr_from_type(r#type)
5281 }
5282}
5283#[derive(Clone, Copy, Default)]
5284pub struct IterableOpDevGetDoRequest<'a> {
5285 buf: &'a [u8],
5286 pos: usize,
5287 orig_loc: usize,
5288}
5289impl<'a> IterableOpDevGetDoRequest<'a> {
5290 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5291 Self {
5292 buf,
5293 pos: 0,
5294 orig_loc,
5295 }
5296 }
5297 pub fn get_buf(&self) -> &'a [u8] {
5298 self.buf
5299 }
5300}
5301impl<'a> Iterator for IterableOpDevGetDoRequest<'a> {
5302 type Item = Result<OpDevGetDoRequest, ErrorContext>;
5303 fn next(&mut self) -> Option<Self::Item> {
5304 let pos = self.pos;
5305 let mut r#type;
5306 loop {
5307 r#type = None;
5308 if self.buf.len() == self.pos {
5309 return None;
5310 }
5311 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5312 break;
5313 };
5314 r#type = Some(header.r#type);
5315 let res = match header.r#type {
5316 1u16 => OpDevGetDoRequest::Ifindex({
5317 let res = parse_u32(next);
5318 let Some(val) = res else { break };
5319 val
5320 }),
5321 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5322 n => continue,
5323 };
5324 return Some(Ok(res));
5325 }
5326 Some(Err(ErrorContext::new(
5327 "OpDevGetDoRequest",
5328 r#type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5329 self.orig_loc,
5330 self.buf.as_ptr().wrapping_add(pos) as usize,
5331 )))
5332 }
5333}
5334impl std::fmt::Debug for IterableOpDevGetDoRequest<'_> {
5335 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5336 let mut fmt = f.debug_struct("OpDevGetDoRequest");
5337 for attr in self.clone() {
5338 let attr = match attr {
5339 Ok(a) => a,
5340 Err(err) => {
5341 fmt.finish()?;
5342 f.write_str("Err(")?;
5343 err.fmt(f)?;
5344 return f.write_str(")");
5345 }
5346 };
5347 match attr {
5348 OpDevGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
5349 };
5350 }
5351 fmt.finish()
5352 }
5353}
5354impl IterableOpDevGetDoRequest<'_> {
5355 pub fn lookup_attr(
5356 &self,
5357 offset: usize,
5358 missing_type: Option<u16>,
5359 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5360 let mut stack = Vec::new();
5361 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5362 if cur == offset + PushBuiltinNfgenmsg::len() {
5363 stack.push(("OpDevGetDoRequest", offset));
5364 return (
5365 stack,
5366 missing_type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5367 );
5368 }
5369 if cur > offset || cur + self.buf.len() < offset {
5370 return (stack, None);
5371 }
5372 let mut attrs = self.clone();
5373 let mut last_off = cur + attrs.pos;
5374 while let Some(attr) = attrs.next() {
5375 let Ok(attr) = attr else { break };
5376 match attr {
5377 OpDevGetDoRequest::Ifindex(val) => {
5378 if last_off == offset {
5379 stack.push(("Ifindex", last_off));
5380 break;
5381 }
5382 }
5383 _ => {}
5384 };
5385 last_off = cur + attrs.pos;
5386 }
5387 if !stack.is_empty() {
5388 stack.push(("OpDevGetDoRequest", cur));
5389 }
5390 (stack, None)
5391 }
5392}
5393#[doc = "Get / dump information about a netdev."]
5394pub struct PushOpDevGetDoReply<Prev: Rec> {
5395 pub(crate) prev: Option<Prev>,
5396 pub(crate) header_offset: Option<usize>,
5397}
5398impl<Prev: Rec> Rec for PushOpDevGetDoReply<Prev> {
5399 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5400 self.prev.as_mut().unwrap().as_rec_mut()
5401 }
5402 fn as_rec(&self) -> &Vec<u8> {
5403 self.prev.as_ref().unwrap().as_rec()
5404 }
5405}
5406impl<Prev: Rec> PushOpDevGetDoReply<Prev> {
5407 pub fn new(mut prev: Prev) -> Self {
5408 Self::write_header(&mut prev);
5409 Self::new_without_header(prev)
5410 }
5411 fn new_without_header(prev: Prev) -> Self {
5412 Self {
5413 prev: Some(prev),
5414 header_offset: None,
5415 }
5416 }
5417 fn write_header(prev: &mut Prev) {
5418 let mut header = PushBuiltinNfgenmsg::new();
5419 header.set_cmd(1u8);
5420 header.set_version(1u8);
5421 prev.as_rec_mut().extend(header.as_slice());
5422 }
5423 pub fn end_nested(mut self) -> Prev {
5424 let mut prev = self.prev.take().unwrap();
5425 if let Some(header_offset) = &self.header_offset {
5426 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5427 }
5428 prev
5429 }
5430 #[doc = "netdev ifindex"]
5431 pub fn push_ifindex(mut self, value: u32) -> Self {
5432 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5433 self.as_rec_mut().extend(value.to_ne_bytes());
5434 self
5435 }
5436 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5437 pub fn push_xdp_features(mut self, value: u64) -> Self {
5438 push_header(self.as_rec_mut(), 3u16, 8 as u16);
5439 self.as_rec_mut().extend(value.to_ne_bytes());
5440 self
5441 }
5442 #[doc = "max fragment count supported by ZC driver"]
5443 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
5444 push_header(self.as_rec_mut(), 4u16, 4 as u16);
5445 self.as_rec_mut().extend(value.to_ne_bytes());
5446 self
5447 }
5448 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5449 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
5450 push_header(self.as_rec_mut(), 5u16, 8 as u16);
5451 self.as_rec_mut().extend(value.to_ne_bytes());
5452 self
5453 }
5454 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5455 pub fn push_xsk_features(mut self, value: u64) -> Self {
5456 push_header(self.as_rec_mut(), 6u16, 8 as u16);
5457 self.as_rec_mut().extend(value.to_ne_bytes());
5458 self
5459 }
5460}
5461impl<Prev: Rec> Drop for PushOpDevGetDoReply<Prev> {
5462 fn drop(&mut self) {
5463 if let Some(prev) = &mut self.prev {
5464 if let Some(header_offset) = &self.header_offset {
5465 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5466 }
5467 }
5468 }
5469}
5470#[doc = "Get / dump information about a netdev."]
5471#[derive(Clone)]
5472pub enum OpDevGetDoReply {
5473 #[doc = "netdev ifindex"]
5474 Ifindex(u32),
5475 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5476 XdpFeatures(u64),
5477 #[doc = "max fragment count supported by ZC driver"]
5478 XdpZcMaxSegs(u32),
5479 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5480 XdpRxMetadataFeatures(u64),
5481 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5482 XskFeatures(u64),
5483}
5484impl<'a> IterableOpDevGetDoReply<'a> {
5485 #[doc = "netdev ifindex"]
5486 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5487 let mut iter = self.clone();
5488 iter.pos = 0;
5489 for attr in iter {
5490 if let OpDevGetDoReply::Ifindex(val) = attr? {
5491 return Ok(val);
5492 }
5493 }
5494 Err(ErrorContext::new_missing(
5495 "OpDevGetDoReply",
5496 "Ifindex",
5497 self.orig_loc,
5498 self.buf.as_ptr() as usize,
5499 ))
5500 }
5501 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5502 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
5503 let mut iter = self.clone();
5504 iter.pos = 0;
5505 for attr in iter {
5506 if let OpDevGetDoReply::XdpFeatures(val) = attr? {
5507 return Ok(val);
5508 }
5509 }
5510 Err(ErrorContext::new_missing(
5511 "OpDevGetDoReply",
5512 "XdpFeatures",
5513 self.orig_loc,
5514 self.buf.as_ptr() as usize,
5515 ))
5516 }
5517 #[doc = "max fragment count supported by ZC driver"]
5518 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
5519 let mut iter = self.clone();
5520 iter.pos = 0;
5521 for attr in iter {
5522 if let OpDevGetDoReply::XdpZcMaxSegs(val) = attr? {
5523 return Ok(val);
5524 }
5525 }
5526 Err(ErrorContext::new_missing(
5527 "OpDevGetDoReply",
5528 "XdpZcMaxSegs",
5529 self.orig_loc,
5530 self.buf.as_ptr() as usize,
5531 ))
5532 }
5533 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5534 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
5535 let mut iter = self.clone();
5536 iter.pos = 0;
5537 for attr in iter {
5538 if let OpDevGetDoReply::XdpRxMetadataFeatures(val) = attr? {
5539 return Ok(val);
5540 }
5541 }
5542 Err(ErrorContext::new_missing(
5543 "OpDevGetDoReply",
5544 "XdpRxMetadataFeatures",
5545 self.orig_loc,
5546 self.buf.as_ptr() as usize,
5547 ))
5548 }
5549 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5550 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
5551 let mut iter = self.clone();
5552 iter.pos = 0;
5553 for attr in iter {
5554 if let OpDevGetDoReply::XskFeatures(val) = attr? {
5555 return Ok(val);
5556 }
5557 }
5558 Err(ErrorContext::new_missing(
5559 "OpDevGetDoReply",
5560 "XskFeatures",
5561 self.orig_loc,
5562 self.buf.as_ptr() as usize,
5563 ))
5564 }
5565}
5566impl OpDevGetDoReply {
5567 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoReply<'a> {
5568 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5569 IterableOpDevGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
5570 }
5571 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5572 Dev::attr_from_type(r#type)
5573 }
5574}
5575#[derive(Clone, Copy, Default)]
5576pub struct IterableOpDevGetDoReply<'a> {
5577 buf: &'a [u8],
5578 pos: usize,
5579 orig_loc: usize,
5580}
5581impl<'a> IterableOpDevGetDoReply<'a> {
5582 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5583 Self {
5584 buf,
5585 pos: 0,
5586 orig_loc,
5587 }
5588 }
5589 pub fn get_buf(&self) -> &'a [u8] {
5590 self.buf
5591 }
5592}
5593impl<'a> Iterator for IterableOpDevGetDoReply<'a> {
5594 type Item = Result<OpDevGetDoReply, ErrorContext>;
5595 fn next(&mut self) -> Option<Self::Item> {
5596 let pos = self.pos;
5597 let mut r#type;
5598 loop {
5599 r#type = None;
5600 if self.buf.len() == self.pos {
5601 return None;
5602 }
5603 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5604 break;
5605 };
5606 r#type = Some(header.r#type);
5607 let res = match header.r#type {
5608 1u16 => OpDevGetDoReply::Ifindex({
5609 let res = parse_u32(next);
5610 let Some(val) = res else { break };
5611 val
5612 }),
5613 3u16 => OpDevGetDoReply::XdpFeatures({
5614 let res = parse_u64(next);
5615 let Some(val) = res else { break };
5616 val
5617 }),
5618 4u16 => OpDevGetDoReply::XdpZcMaxSegs({
5619 let res = parse_u32(next);
5620 let Some(val) = res else { break };
5621 val
5622 }),
5623 5u16 => OpDevGetDoReply::XdpRxMetadataFeatures({
5624 let res = parse_u64(next);
5625 let Some(val) = res else { break };
5626 val
5627 }),
5628 6u16 => OpDevGetDoReply::XskFeatures({
5629 let res = parse_u64(next);
5630 let Some(val) = res else { break };
5631 val
5632 }),
5633 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5634 n => continue,
5635 };
5636 return Some(Ok(res));
5637 }
5638 Some(Err(ErrorContext::new(
5639 "OpDevGetDoReply",
5640 r#type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5641 self.orig_loc,
5642 self.buf.as_ptr().wrapping_add(pos) as usize,
5643 )))
5644 }
5645}
5646impl std::fmt::Debug for IterableOpDevGetDoReply<'_> {
5647 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5648 let mut fmt = f.debug_struct("OpDevGetDoReply");
5649 for attr in self.clone() {
5650 let attr = match attr {
5651 Ok(a) => a,
5652 Err(err) => {
5653 fmt.finish()?;
5654 f.write_str("Err(")?;
5655 err.fmt(f)?;
5656 return f.write_str(")");
5657 }
5658 };
5659 match attr {
5660 OpDevGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
5661 OpDevGetDoReply::XdpFeatures(val) => {
5662 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5663 }
5664 OpDevGetDoReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5665 OpDevGetDoReply::XdpRxMetadataFeatures(val) => fmt.field(
5666 "XdpRxMetadataFeatures",
5667 &FormatFlags(val.into(), XdpRxMetadata::from_value),
5668 ),
5669 OpDevGetDoReply::XskFeatures(val) => fmt.field(
5670 "XskFeatures",
5671 &FormatFlags(val.into(), XskFlags::from_value),
5672 ),
5673 };
5674 }
5675 fmt.finish()
5676 }
5677}
5678impl IterableOpDevGetDoReply<'_> {
5679 pub fn lookup_attr(
5680 &self,
5681 offset: usize,
5682 missing_type: Option<u16>,
5683 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5684 let mut stack = Vec::new();
5685 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5686 if cur == offset + PushBuiltinNfgenmsg::len() {
5687 stack.push(("OpDevGetDoReply", offset));
5688 return (
5689 stack,
5690 missing_type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5691 );
5692 }
5693 if cur > offset || cur + self.buf.len() < offset {
5694 return (stack, None);
5695 }
5696 let mut attrs = self.clone();
5697 let mut last_off = cur + attrs.pos;
5698 while let Some(attr) = attrs.next() {
5699 let Ok(attr) = attr else { break };
5700 match attr {
5701 OpDevGetDoReply::Ifindex(val) => {
5702 if last_off == offset {
5703 stack.push(("Ifindex", last_off));
5704 break;
5705 }
5706 }
5707 OpDevGetDoReply::XdpFeatures(val) => {
5708 if last_off == offset {
5709 stack.push(("XdpFeatures", last_off));
5710 break;
5711 }
5712 }
5713 OpDevGetDoReply::XdpZcMaxSegs(val) => {
5714 if last_off == offset {
5715 stack.push(("XdpZcMaxSegs", last_off));
5716 break;
5717 }
5718 }
5719 OpDevGetDoReply::XdpRxMetadataFeatures(val) => {
5720 if last_off == offset {
5721 stack.push(("XdpRxMetadataFeatures", last_off));
5722 break;
5723 }
5724 }
5725 OpDevGetDoReply::XskFeatures(val) => {
5726 if last_off == offset {
5727 stack.push(("XskFeatures", last_off));
5728 break;
5729 }
5730 }
5731 _ => {}
5732 };
5733 last_off = cur + attrs.pos;
5734 }
5735 if !stack.is_empty() {
5736 stack.push(("OpDevGetDoReply", cur));
5737 }
5738 (stack, None)
5739 }
5740}
5741#[derive(Debug)]
5742pub struct RequestOpDevGetDoRequest<'r> {
5743 request: Request<'r>,
5744}
5745impl<'r> RequestOpDevGetDoRequest<'r> {
5746 pub fn new(mut request: Request<'r>) -> Self {
5747 PushOpDevGetDoRequest::write_header(&mut request.buf_mut());
5748 Self { request: request }
5749 }
5750 pub fn encode(&mut self) -> PushOpDevGetDoRequest<&mut Vec<u8>> {
5751 PushOpDevGetDoRequest::new_without_header(self.request.buf_mut())
5752 }
5753 pub fn into_encoder(self) -> PushOpDevGetDoRequest<RequestBuf<'r>> {
5754 PushOpDevGetDoRequest::new_without_header(self.request.buf)
5755 }
5756 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpDevGetDoRequest<'buf> {
5757 OpDevGetDoRequest::new(buf)
5758 }
5759}
5760impl NetlinkRequest for RequestOpDevGetDoRequest<'_> {
5761 fn protocol(&self) -> Protocol {
5762 Protocol::Generic("netdev".as_bytes())
5763 }
5764 fn flags(&self) -> u16 {
5765 self.request.flags
5766 }
5767 fn payload(&self) -> &[u8] {
5768 self.request.buf()
5769 }
5770 type ReplyType<'buf> = IterableOpDevGetDoReply<'buf>;
5771 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5772 OpDevGetDoReply::new(buf)
5773 }
5774 fn lookup(
5775 buf: &[u8],
5776 offset: usize,
5777 missing_type: Option<u16>,
5778 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5779 OpDevGetDoRequest::new(buf).lookup_attr(offset, missing_type)
5780 }
5781}
5782#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5783pub struct PushOpPagePoolGetDumpRequest<Prev: Rec> {
5784 pub(crate) prev: Option<Prev>,
5785 pub(crate) header_offset: Option<usize>,
5786}
5787impl<Prev: Rec> Rec for PushOpPagePoolGetDumpRequest<Prev> {
5788 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5789 self.prev.as_mut().unwrap().as_rec_mut()
5790 }
5791 fn as_rec(&self) -> &Vec<u8> {
5792 self.prev.as_ref().unwrap().as_rec()
5793 }
5794}
5795impl<Prev: Rec> PushOpPagePoolGetDumpRequest<Prev> {
5796 pub fn new(mut prev: Prev) -> Self {
5797 Self::write_header(&mut prev);
5798 Self::new_without_header(prev)
5799 }
5800 fn new_without_header(prev: Prev) -> Self {
5801 Self {
5802 prev: Some(prev),
5803 header_offset: None,
5804 }
5805 }
5806 fn write_header(prev: &mut Prev) {
5807 let mut header = PushBuiltinNfgenmsg::new();
5808 header.set_cmd(5u8);
5809 header.set_version(1u8);
5810 prev.as_rec_mut().extend(header.as_slice());
5811 }
5812 pub fn end_nested(mut self) -> Prev {
5813 let mut prev = self.prev.take().unwrap();
5814 if let Some(header_offset) = &self.header_offset {
5815 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5816 }
5817 prev
5818 }
5819}
5820impl<Prev: Rec> Drop for PushOpPagePoolGetDumpRequest<Prev> {
5821 fn drop(&mut self) {
5822 if let Some(prev) = &mut self.prev {
5823 if let Some(header_offset) = &self.header_offset {
5824 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5825 }
5826 }
5827 }
5828}
5829#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5830#[derive(Clone)]
5831pub enum OpPagePoolGetDumpRequest {}
5832impl<'a> IterableOpPagePoolGetDumpRequest<'a> {}
5833impl OpPagePoolGetDumpRequest {
5834 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpRequest<'a> {
5835 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5836 IterableOpPagePoolGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
5837 }
5838 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5839 PagePool::attr_from_type(r#type)
5840 }
5841}
5842#[derive(Clone, Copy, Default)]
5843pub struct IterableOpPagePoolGetDumpRequest<'a> {
5844 buf: &'a [u8],
5845 pos: usize,
5846 orig_loc: usize,
5847}
5848impl<'a> IterableOpPagePoolGetDumpRequest<'a> {
5849 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5850 Self {
5851 buf,
5852 pos: 0,
5853 orig_loc,
5854 }
5855 }
5856 pub fn get_buf(&self) -> &'a [u8] {
5857 self.buf
5858 }
5859}
5860impl<'a> Iterator for IterableOpPagePoolGetDumpRequest<'a> {
5861 type Item = Result<OpPagePoolGetDumpRequest, ErrorContext>;
5862 fn next(&mut self) -> Option<Self::Item> {
5863 let pos = self.pos;
5864 let mut r#type;
5865 loop {
5866 r#type = None;
5867 if self.buf.len() == self.pos {
5868 return None;
5869 }
5870 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
5871 break;
5872 };
5873 r#type = Some(header.r#type);
5874 let res = match header.r#type {
5875 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
5876 n => continue,
5877 };
5878 return Some(Ok(res));
5879 }
5880 Some(Err(ErrorContext::new(
5881 "OpPagePoolGetDumpRequest",
5882 r#type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5883 self.orig_loc,
5884 self.buf.as_ptr().wrapping_add(pos) as usize,
5885 )))
5886 }
5887}
5888impl std::fmt::Debug for IterableOpPagePoolGetDumpRequest<'_> {
5889 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5890 let mut fmt = f.debug_struct("OpPagePoolGetDumpRequest");
5891 for attr in self.clone() {
5892 let attr = match attr {
5893 Ok(a) => a,
5894 Err(err) => {
5895 fmt.finish()?;
5896 f.write_str("Err(")?;
5897 err.fmt(f)?;
5898 return f.write_str(")");
5899 }
5900 };
5901 match attr {};
5902 }
5903 fmt.finish()
5904 }
5905}
5906impl IterableOpPagePoolGetDumpRequest<'_> {
5907 pub fn lookup_attr(
5908 &self,
5909 offset: usize,
5910 missing_type: Option<u16>,
5911 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5912 let mut stack = Vec::new();
5913 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5914 if cur == offset + PushBuiltinNfgenmsg::len() {
5915 stack.push(("OpPagePoolGetDumpRequest", offset));
5916 return (
5917 stack,
5918 missing_type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5919 );
5920 }
5921 (stack, None)
5922 }
5923}
5924#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5925pub struct PushOpPagePoolGetDumpReply<Prev: Rec> {
5926 pub(crate) prev: Option<Prev>,
5927 pub(crate) header_offset: Option<usize>,
5928}
5929impl<Prev: Rec> Rec for PushOpPagePoolGetDumpReply<Prev> {
5930 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5931 self.prev.as_mut().unwrap().as_rec_mut()
5932 }
5933 fn as_rec(&self) -> &Vec<u8> {
5934 self.prev.as_ref().unwrap().as_rec()
5935 }
5936}
5937impl<Prev: Rec> PushOpPagePoolGetDumpReply<Prev> {
5938 pub fn new(mut prev: Prev) -> Self {
5939 Self::write_header(&mut prev);
5940 Self::new_without_header(prev)
5941 }
5942 fn new_without_header(prev: Prev) -> Self {
5943 Self {
5944 prev: Some(prev),
5945 header_offset: None,
5946 }
5947 }
5948 fn write_header(prev: &mut Prev) {
5949 let mut header = PushBuiltinNfgenmsg::new();
5950 header.set_cmd(5u8);
5951 header.set_version(1u8);
5952 prev.as_rec_mut().extend(header.as_slice());
5953 }
5954 pub fn end_nested(mut self) -> Prev {
5955 let mut prev = self.prev.take().unwrap();
5956 if let Some(header_offset) = &self.header_offset {
5957 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5958 }
5959 prev
5960 }
5961 #[doc = "Unique ID of a Page Pool instance."]
5962 pub fn push_id(mut self, value: u32) -> Self {
5963 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5964 self.as_rec_mut().extend(value.to_ne_bytes());
5965 self
5966 }
5967 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
5968 pub fn push_ifindex(mut self, value: u32) -> Self {
5969 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5970 self.as_rec_mut().extend(value.to_ne_bytes());
5971 self
5972 }
5973 #[doc = "Id of NAPI using this Page Pool instance."]
5974 pub fn push_napi_id(mut self, value: u32) -> Self {
5975 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5976 self.as_rec_mut().extend(value.to_ne_bytes());
5977 self
5978 }
5979 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
5980 pub fn push_inflight(mut self, value: u32) -> Self {
5981 push_header(self.as_rec_mut(), 4u16, 4 as u16);
5982 self.as_rec_mut().extend(value.to_ne_bytes());
5983 self
5984 }
5985 #[doc = "Amount of memory held by inflight pages.\n"]
5986 pub fn push_inflight_mem(mut self, value: u32) -> Self {
5987 push_header(self.as_rec_mut(), 5u16, 4 as u16);
5988 self.as_rec_mut().extend(value.to_ne_bytes());
5989 self
5990 }
5991 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
5992 pub fn push_detach_time(mut self, value: u32) -> Self {
5993 push_header(self.as_rec_mut(), 6u16, 4 as u16);
5994 self.as_rec_mut().extend(value.to_ne_bytes());
5995 self
5996 }
5997 #[doc = "ID of the dmabuf this page-pool is attached to."]
5998 pub fn push_dmabuf(mut self, value: u32) -> Self {
5999 push_header(self.as_rec_mut(), 7u16, 4 as u16);
6000 self.as_rec_mut().extend(value.to_ne_bytes());
6001 self
6002 }
6003 #[doc = "io-uring memory provider information."]
6004 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6005 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6006 PushIoUringProviderInfo {
6007 prev: Some(self),
6008 header_offset: Some(header_offset),
6009 }
6010 }
6011}
6012impl<Prev: Rec> Drop for PushOpPagePoolGetDumpReply<Prev> {
6013 fn drop(&mut self) {
6014 if let Some(prev) = &mut self.prev {
6015 if let Some(header_offset) = &self.header_offset {
6016 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6017 }
6018 }
6019 }
6020}
6021#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6022#[derive(Clone)]
6023pub enum OpPagePoolGetDumpReply<'a> {
6024 #[doc = "Unique ID of a Page Pool instance."]
6025 Id(u32),
6026 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6027 Ifindex(u32),
6028 #[doc = "Id of NAPI using this Page Pool instance."]
6029 NapiId(u32),
6030 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6031 Inflight(u32),
6032 #[doc = "Amount of memory held by inflight pages.\n"]
6033 InflightMem(u32),
6034 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6035 DetachTime(u32),
6036 #[doc = "ID of the dmabuf this page-pool is attached to."]
6037 Dmabuf(u32),
6038 #[doc = "io-uring memory provider information."]
6039 IoUring(IterableIoUringProviderInfo<'a>),
6040}
6041impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6042 #[doc = "Unique ID of a Page Pool instance."]
6043 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6044 let mut iter = self.clone();
6045 iter.pos = 0;
6046 for attr in iter {
6047 if let OpPagePoolGetDumpReply::Id(val) = attr? {
6048 return Ok(val);
6049 }
6050 }
6051 Err(ErrorContext::new_missing(
6052 "OpPagePoolGetDumpReply",
6053 "Id",
6054 self.orig_loc,
6055 self.buf.as_ptr() as usize,
6056 ))
6057 }
6058 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6059 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6060 let mut iter = self.clone();
6061 iter.pos = 0;
6062 for attr in iter {
6063 if let OpPagePoolGetDumpReply::Ifindex(val) = attr? {
6064 return Ok(val);
6065 }
6066 }
6067 Err(ErrorContext::new_missing(
6068 "OpPagePoolGetDumpReply",
6069 "Ifindex",
6070 self.orig_loc,
6071 self.buf.as_ptr() as usize,
6072 ))
6073 }
6074 #[doc = "Id of NAPI using this Page Pool instance."]
6075 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6076 let mut iter = self.clone();
6077 iter.pos = 0;
6078 for attr in iter {
6079 if let OpPagePoolGetDumpReply::NapiId(val) = attr? {
6080 return Ok(val);
6081 }
6082 }
6083 Err(ErrorContext::new_missing(
6084 "OpPagePoolGetDumpReply",
6085 "NapiId",
6086 self.orig_loc,
6087 self.buf.as_ptr() as usize,
6088 ))
6089 }
6090 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6091 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6092 let mut iter = self.clone();
6093 iter.pos = 0;
6094 for attr in iter {
6095 if let OpPagePoolGetDumpReply::Inflight(val) = attr? {
6096 return Ok(val);
6097 }
6098 }
6099 Err(ErrorContext::new_missing(
6100 "OpPagePoolGetDumpReply",
6101 "Inflight",
6102 self.orig_loc,
6103 self.buf.as_ptr() as usize,
6104 ))
6105 }
6106 #[doc = "Amount of memory held by inflight pages.\n"]
6107 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6108 let mut iter = self.clone();
6109 iter.pos = 0;
6110 for attr in iter {
6111 if let OpPagePoolGetDumpReply::InflightMem(val) = attr? {
6112 return Ok(val);
6113 }
6114 }
6115 Err(ErrorContext::new_missing(
6116 "OpPagePoolGetDumpReply",
6117 "InflightMem",
6118 self.orig_loc,
6119 self.buf.as_ptr() as usize,
6120 ))
6121 }
6122 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6123 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6124 let mut iter = self.clone();
6125 iter.pos = 0;
6126 for attr in iter {
6127 if let OpPagePoolGetDumpReply::DetachTime(val) = attr? {
6128 return Ok(val);
6129 }
6130 }
6131 Err(ErrorContext::new_missing(
6132 "OpPagePoolGetDumpReply",
6133 "DetachTime",
6134 self.orig_loc,
6135 self.buf.as_ptr() as usize,
6136 ))
6137 }
6138 #[doc = "ID of the dmabuf this page-pool is attached to."]
6139 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6140 let mut iter = self.clone();
6141 iter.pos = 0;
6142 for attr in iter {
6143 if let OpPagePoolGetDumpReply::Dmabuf(val) = attr? {
6144 return Ok(val);
6145 }
6146 }
6147 Err(ErrorContext::new_missing(
6148 "OpPagePoolGetDumpReply",
6149 "Dmabuf",
6150 self.orig_loc,
6151 self.buf.as_ptr() as usize,
6152 ))
6153 }
6154 #[doc = "io-uring memory provider information."]
6155 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6156 let mut iter = self.clone();
6157 iter.pos = 0;
6158 for attr in iter {
6159 if let OpPagePoolGetDumpReply::IoUring(val) = attr? {
6160 return Ok(val);
6161 }
6162 }
6163 Err(ErrorContext::new_missing(
6164 "OpPagePoolGetDumpReply",
6165 "IoUring",
6166 self.orig_loc,
6167 self.buf.as_ptr() as usize,
6168 ))
6169 }
6170}
6171impl OpPagePoolGetDumpReply<'_> {
6172 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpReply<'a> {
6173 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6174 IterableOpPagePoolGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
6175 }
6176 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6177 PagePool::attr_from_type(r#type)
6178 }
6179}
6180#[derive(Clone, Copy, Default)]
6181pub struct IterableOpPagePoolGetDumpReply<'a> {
6182 buf: &'a [u8],
6183 pos: usize,
6184 orig_loc: usize,
6185}
6186impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6187 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6188 Self {
6189 buf,
6190 pos: 0,
6191 orig_loc,
6192 }
6193 }
6194 pub fn get_buf(&self) -> &'a [u8] {
6195 self.buf
6196 }
6197}
6198impl<'a> Iterator for IterableOpPagePoolGetDumpReply<'a> {
6199 type Item = Result<OpPagePoolGetDumpReply<'a>, ErrorContext>;
6200 fn next(&mut self) -> Option<Self::Item> {
6201 let pos = self.pos;
6202 let mut r#type;
6203 loop {
6204 r#type = None;
6205 if self.buf.len() == self.pos {
6206 return None;
6207 }
6208 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6209 break;
6210 };
6211 r#type = Some(header.r#type);
6212 let res = match header.r#type {
6213 1u16 => OpPagePoolGetDumpReply::Id({
6214 let res = parse_u32(next);
6215 let Some(val) = res else { break };
6216 val
6217 }),
6218 2u16 => OpPagePoolGetDumpReply::Ifindex({
6219 let res = parse_u32(next);
6220 let Some(val) = res else { break };
6221 val
6222 }),
6223 3u16 => OpPagePoolGetDumpReply::NapiId({
6224 let res = parse_u32(next);
6225 let Some(val) = res else { break };
6226 val
6227 }),
6228 4u16 => OpPagePoolGetDumpReply::Inflight({
6229 let res = parse_u32(next);
6230 let Some(val) = res else { break };
6231 val
6232 }),
6233 5u16 => OpPagePoolGetDumpReply::InflightMem({
6234 let res = parse_u32(next);
6235 let Some(val) = res else { break };
6236 val
6237 }),
6238 6u16 => OpPagePoolGetDumpReply::DetachTime({
6239 let res = parse_u32(next);
6240 let Some(val) = res else { break };
6241 val
6242 }),
6243 7u16 => OpPagePoolGetDumpReply::Dmabuf({
6244 let res = parse_u32(next);
6245 let Some(val) = res else { break };
6246 val
6247 }),
6248 8u16 => OpPagePoolGetDumpReply::IoUring({
6249 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6250 let Some(val) = res else { break };
6251 val
6252 }),
6253 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6254 n => continue,
6255 };
6256 return Some(Ok(res));
6257 }
6258 Some(Err(ErrorContext::new(
6259 "OpPagePoolGetDumpReply",
6260 r#type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6261 self.orig_loc,
6262 self.buf.as_ptr().wrapping_add(pos) as usize,
6263 )))
6264 }
6265}
6266impl<'a> std::fmt::Debug for IterableOpPagePoolGetDumpReply<'_> {
6267 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6268 let mut fmt = f.debug_struct("OpPagePoolGetDumpReply");
6269 for attr in self.clone() {
6270 let attr = match attr {
6271 Ok(a) => a,
6272 Err(err) => {
6273 fmt.finish()?;
6274 f.write_str("Err(")?;
6275 err.fmt(f)?;
6276 return f.write_str(")");
6277 }
6278 };
6279 match attr {
6280 OpPagePoolGetDumpReply::Id(val) => fmt.field("Id", &val),
6281 OpPagePoolGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
6282 OpPagePoolGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
6283 OpPagePoolGetDumpReply::Inflight(val) => fmt.field("Inflight", &val),
6284 OpPagePoolGetDumpReply::InflightMem(val) => fmt.field("InflightMem", &val),
6285 OpPagePoolGetDumpReply::DetachTime(val) => fmt.field("DetachTime", &val),
6286 OpPagePoolGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6287 OpPagePoolGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
6288 };
6289 }
6290 fmt.finish()
6291 }
6292}
6293impl IterableOpPagePoolGetDumpReply<'_> {
6294 pub fn lookup_attr(
6295 &self,
6296 offset: usize,
6297 missing_type: Option<u16>,
6298 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6299 let mut stack = Vec::new();
6300 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6301 if cur == offset + PushBuiltinNfgenmsg::len() {
6302 stack.push(("OpPagePoolGetDumpReply", offset));
6303 return (
6304 stack,
6305 missing_type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6306 );
6307 }
6308 if cur > offset || cur + self.buf.len() < offset {
6309 return (stack, None);
6310 }
6311 let mut attrs = self.clone();
6312 let mut last_off = cur + attrs.pos;
6313 let mut missing = None;
6314 while let Some(attr) = attrs.next() {
6315 let Ok(attr) = attr else { break };
6316 match attr {
6317 OpPagePoolGetDumpReply::Id(val) => {
6318 if last_off == offset {
6319 stack.push(("Id", last_off));
6320 break;
6321 }
6322 }
6323 OpPagePoolGetDumpReply::Ifindex(val) => {
6324 if last_off == offset {
6325 stack.push(("Ifindex", last_off));
6326 break;
6327 }
6328 }
6329 OpPagePoolGetDumpReply::NapiId(val) => {
6330 if last_off == offset {
6331 stack.push(("NapiId", last_off));
6332 break;
6333 }
6334 }
6335 OpPagePoolGetDumpReply::Inflight(val) => {
6336 if last_off == offset {
6337 stack.push(("Inflight", last_off));
6338 break;
6339 }
6340 }
6341 OpPagePoolGetDumpReply::InflightMem(val) => {
6342 if last_off == offset {
6343 stack.push(("InflightMem", last_off));
6344 break;
6345 }
6346 }
6347 OpPagePoolGetDumpReply::DetachTime(val) => {
6348 if last_off == offset {
6349 stack.push(("DetachTime", last_off));
6350 break;
6351 }
6352 }
6353 OpPagePoolGetDumpReply::Dmabuf(val) => {
6354 if last_off == offset {
6355 stack.push(("Dmabuf", last_off));
6356 break;
6357 }
6358 }
6359 OpPagePoolGetDumpReply::IoUring(val) => {
6360 (stack, missing) = val.lookup_attr(offset, missing_type);
6361 if !stack.is_empty() {
6362 break;
6363 }
6364 }
6365 _ => {}
6366 };
6367 last_off = cur + attrs.pos;
6368 }
6369 if !stack.is_empty() {
6370 stack.push(("OpPagePoolGetDumpReply", cur));
6371 }
6372 (stack, missing)
6373 }
6374}
6375#[derive(Debug)]
6376pub struct RequestOpPagePoolGetDumpRequest<'r> {
6377 request: Request<'r>,
6378}
6379impl<'r> RequestOpPagePoolGetDumpRequest<'r> {
6380 pub fn new(mut request: Request<'r>) -> Self {
6381 PushOpPagePoolGetDumpRequest::write_header(&mut request.buf_mut());
6382 Self {
6383 request: request.set_dump(),
6384 }
6385 }
6386 pub fn encode(&mut self) -> PushOpPagePoolGetDumpRequest<&mut Vec<u8>> {
6387 PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf_mut())
6388 }
6389 pub fn into_encoder(self) -> PushOpPagePoolGetDumpRequest<RequestBuf<'r>> {
6390 PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf)
6391 }
6392 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolGetDumpRequest<'buf> {
6393 OpPagePoolGetDumpRequest::new(buf)
6394 }
6395}
6396impl NetlinkRequest for RequestOpPagePoolGetDumpRequest<'_> {
6397 fn protocol(&self) -> Protocol {
6398 Protocol::Generic("netdev".as_bytes())
6399 }
6400 fn flags(&self) -> u16 {
6401 self.request.flags
6402 }
6403 fn payload(&self) -> &[u8] {
6404 self.request.buf()
6405 }
6406 type ReplyType<'buf> = IterableOpPagePoolGetDumpReply<'buf>;
6407 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6408 OpPagePoolGetDumpReply::new(buf)
6409 }
6410 fn lookup(
6411 buf: &[u8],
6412 offset: usize,
6413 missing_type: Option<u16>,
6414 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6415 OpPagePoolGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
6416 }
6417}
6418#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6419pub struct PushOpPagePoolGetDoRequest<Prev: Rec> {
6420 pub(crate) prev: Option<Prev>,
6421 pub(crate) header_offset: Option<usize>,
6422}
6423impl<Prev: Rec> Rec for PushOpPagePoolGetDoRequest<Prev> {
6424 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6425 self.prev.as_mut().unwrap().as_rec_mut()
6426 }
6427 fn as_rec(&self) -> &Vec<u8> {
6428 self.prev.as_ref().unwrap().as_rec()
6429 }
6430}
6431impl<Prev: Rec> PushOpPagePoolGetDoRequest<Prev> {
6432 pub fn new(mut prev: Prev) -> Self {
6433 Self::write_header(&mut prev);
6434 Self::new_without_header(prev)
6435 }
6436 fn new_without_header(prev: Prev) -> Self {
6437 Self {
6438 prev: Some(prev),
6439 header_offset: None,
6440 }
6441 }
6442 fn write_header(prev: &mut Prev) {
6443 let mut header = PushBuiltinNfgenmsg::new();
6444 header.set_cmd(5u8);
6445 header.set_version(1u8);
6446 prev.as_rec_mut().extend(header.as_slice());
6447 }
6448 pub fn end_nested(mut self) -> Prev {
6449 let mut prev = self.prev.take().unwrap();
6450 if let Some(header_offset) = &self.header_offset {
6451 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6452 }
6453 prev
6454 }
6455 #[doc = "Unique ID of a Page Pool instance."]
6456 pub fn push_id(mut self, value: u32) -> Self {
6457 push_header(self.as_rec_mut(), 1u16, 4 as u16);
6458 self.as_rec_mut().extend(value.to_ne_bytes());
6459 self
6460 }
6461}
6462impl<Prev: Rec> Drop for PushOpPagePoolGetDoRequest<Prev> {
6463 fn drop(&mut self) {
6464 if let Some(prev) = &mut self.prev {
6465 if let Some(header_offset) = &self.header_offset {
6466 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6467 }
6468 }
6469 }
6470}
6471#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6472#[derive(Clone)]
6473pub enum OpPagePoolGetDoRequest {
6474 #[doc = "Unique ID of a Page Pool instance."]
6475 Id(u32),
6476}
6477impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6478 #[doc = "Unique ID of a Page Pool instance."]
6479 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6480 let mut iter = self.clone();
6481 iter.pos = 0;
6482 for attr in iter {
6483 if let OpPagePoolGetDoRequest::Id(val) = attr? {
6484 return Ok(val);
6485 }
6486 }
6487 Err(ErrorContext::new_missing(
6488 "OpPagePoolGetDoRequest",
6489 "Id",
6490 self.orig_loc,
6491 self.buf.as_ptr() as usize,
6492 ))
6493 }
6494}
6495impl OpPagePoolGetDoRequest {
6496 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoRequest<'a> {
6497 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6498 IterableOpPagePoolGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
6499 }
6500 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6501 PagePool::attr_from_type(r#type)
6502 }
6503}
6504#[derive(Clone, Copy, Default)]
6505pub struct IterableOpPagePoolGetDoRequest<'a> {
6506 buf: &'a [u8],
6507 pos: usize,
6508 orig_loc: usize,
6509}
6510impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6511 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6512 Self {
6513 buf,
6514 pos: 0,
6515 orig_loc,
6516 }
6517 }
6518 pub fn get_buf(&self) -> &'a [u8] {
6519 self.buf
6520 }
6521}
6522impl<'a> Iterator for IterableOpPagePoolGetDoRequest<'a> {
6523 type Item = Result<OpPagePoolGetDoRequest, ErrorContext>;
6524 fn next(&mut self) -> Option<Self::Item> {
6525 let pos = self.pos;
6526 let mut r#type;
6527 loop {
6528 r#type = None;
6529 if self.buf.len() == self.pos {
6530 return None;
6531 }
6532 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6533 break;
6534 };
6535 r#type = Some(header.r#type);
6536 let res = match header.r#type {
6537 1u16 => OpPagePoolGetDoRequest::Id({
6538 let res = parse_u32(next);
6539 let Some(val) = res else { break };
6540 val
6541 }),
6542 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6543 n => continue,
6544 };
6545 return Some(Ok(res));
6546 }
6547 Some(Err(ErrorContext::new(
6548 "OpPagePoolGetDoRequest",
6549 r#type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6550 self.orig_loc,
6551 self.buf.as_ptr().wrapping_add(pos) as usize,
6552 )))
6553 }
6554}
6555impl std::fmt::Debug for IterableOpPagePoolGetDoRequest<'_> {
6556 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6557 let mut fmt = f.debug_struct("OpPagePoolGetDoRequest");
6558 for attr in self.clone() {
6559 let attr = match attr {
6560 Ok(a) => a,
6561 Err(err) => {
6562 fmt.finish()?;
6563 f.write_str("Err(")?;
6564 err.fmt(f)?;
6565 return f.write_str(")");
6566 }
6567 };
6568 match attr {
6569 OpPagePoolGetDoRequest::Id(val) => fmt.field("Id", &val),
6570 };
6571 }
6572 fmt.finish()
6573 }
6574}
6575impl IterableOpPagePoolGetDoRequest<'_> {
6576 pub fn lookup_attr(
6577 &self,
6578 offset: usize,
6579 missing_type: Option<u16>,
6580 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6581 let mut stack = Vec::new();
6582 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6583 if cur == offset + PushBuiltinNfgenmsg::len() {
6584 stack.push(("OpPagePoolGetDoRequest", offset));
6585 return (
6586 stack,
6587 missing_type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6588 );
6589 }
6590 if cur > offset || cur + self.buf.len() < offset {
6591 return (stack, None);
6592 }
6593 let mut attrs = self.clone();
6594 let mut last_off = cur + attrs.pos;
6595 while let Some(attr) = attrs.next() {
6596 let Ok(attr) = attr else { break };
6597 match attr {
6598 OpPagePoolGetDoRequest::Id(val) => {
6599 if last_off == offset {
6600 stack.push(("Id", last_off));
6601 break;
6602 }
6603 }
6604 _ => {}
6605 };
6606 last_off = cur + attrs.pos;
6607 }
6608 if !stack.is_empty() {
6609 stack.push(("OpPagePoolGetDoRequest", cur));
6610 }
6611 (stack, None)
6612 }
6613}
6614#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6615pub struct PushOpPagePoolGetDoReply<Prev: Rec> {
6616 pub(crate) prev: Option<Prev>,
6617 pub(crate) header_offset: Option<usize>,
6618}
6619impl<Prev: Rec> Rec for PushOpPagePoolGetDoReply<Prev> {
6620 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6621 self.prev.as_mut().unwrap().as_rec_mut()
6622 }
6623 fn as_rec(&self) -> &Vec<u8> {
6624 self.prev.as_ref().unwrap().as_rec()
6625 }
6626}
6627impl<Prev: Rec> PushOpPagePoolGetDoReply<Prev> {
6628 pub fn new(mut prev: Prev) -> Self {
6629 Self::write_header(&mut prev);
6630 Self::new_without_header(prev)
6631 }
6632 fn new_without_header(prev: Prev) -> Self {
6633 Self {
6634 prev: Some(prev),
6635 header_offset: None,
6636 }
6637 }
6638 fn write_header(prev: &mut Prev) {
6639 let mut header = PushBuiltinNfgenmsg::new();
6640 header.set_cmd(5u8);
6641 header.set_version(1u8);
6642 prev.as_rec_mut().extend(header.as_slice());
6643 }
6644 pub fn end_nested(mut self) -> Prev {
6645 let mut prev = self.prev.take().unwrap();
6646 if let Some(header_offset) = &self.header_offset {
6647 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6648 }
6649 prev
6650 }
6651 #[doc = "Unique ID of a Page Pool instance."]
6652 pub fn push_id(mut self, value: u32) -> Self {
6653 push_header(self.as_rec_mut(), 1u16, 4 as u16);
6654 self.as_rec_mut().extend(value.to_ne_bytes());
6655 self
6656 }
6657 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6658 pub fn push_ifindex(mut self, value: u32) -> Self {
6659 push_header(self.as_rec_mut(), 2u16, 4 as u16);
6660 self.as_rec_mut().extend(value.to_ne_bytes());
6661 self
6662 }
6663 #[doc = "Id of NAPI using this Page Pool instance."]
6664 pub fn push_napi_id(mut self, value: u32) -> Self {
6665 push_header(self.as_rec_mut(), 3u16, 4 as u16);
6666 self.as_rec_mut().extend(value.to_ne_bytes());
6667 self
6668 }
6669 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6670 pub fn push_inflight(mut self, value: u32) -> Self {
6671 push_header(self.as_rec_mut(), 4u16, 4 as u16);
6672 self.as_rec_mut().extend(value.to_ne_bytes());
6673 self
6674 }
6675 #[doc = "Amount of memory held by inflight pages.\n"]
6676 pub fn push_inflight_mem(mut self, value: u32) -> Self {
6677 push_header(self.as_rec_mut(), 5u16, 4 as u16);
6678 self.as_rec_mut().extend(value.to_ne_bytes());
6679 self
6680 }
6681 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6682 pub fn push_detach_time(mut self, value: u32) -> Self {
6683 push_header(self.as_rec_mut(), 6u16, 4 as u16);
6684 self.as_rec_mut().extend(value.to_ne_bytes());
6685 self
6686 }
6687 #[doc = "ID of the dmabuf this page-pool is attached to."]
6688 pub fn push_dmabuf(mut self, value: u32) -> Self {
6689 push_header(self.as_rec_mut(), 7u16, 4 as u16);
6690 self.as_rec_mut().extend(value.to_ne_bytes());
6691 self
6692 }
6693 #[doc = "io-uring memory provider information."]
6694 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6695 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6696 PushIoUringProviderInfo {
6697 prev: Some(self),
6698 header_offset: Some(header_offset),
6699 }
6700 }
6701}
6702impl<Prev: Rec> Drop for PushOpPagePoolGetDoReply<Prev> {
6703 fn drop(&mut self) {
6704 if let Some(prev) = &mut self.prev {
6705 if let Some(header_offset) = &self.header_offset {
6706 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6707 }
6708 }
6709 }
6710}
6711#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6712#[derive(Clone)]
6713pub enum OpPagePoolGetDoReply<'a> {
6714 #[doc = "Unique ID of a Page Pool instance."]
6715 Id(u32),
6716 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6717 Ifindex(u32),
6718 #[doc = "Id of NAPI using this Page Pool instance."]
6719 NapiId(u32),
6720 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6721 Inflight(u32),
6722 #[doc = "Amount of memory held by inflight pages.\n"]
6723 InflightMem(u32),
6724 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6725 DetachTime(u32),
6726 #[doc = "ID of the dmabuf this page-pool is attached to."]
6727 Dmabuf(u32),
6728 #[doc = "io-uring memory provider information."]
6729 IoUring(IterableIoUringProviderInfo<'a>),
6730}
6731impl<'a> IterableOpPagePoolGetDoReply<'a> {
6732 #[doc = "Unique ID of a Page Pool instance."]
6733 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6734 let mut iter = self.clone();
6735 iter.pos = 0;
6736 for attr in iter {
6737 if let OpPagePoolGetDoReply::Id(val) = attr? {
6738 return Ok(val);
6739 }
6740 }
6741 Err(ErrorContext::new_missing(
6742 "OpPagePoolGetDoReply",
6743 "Id",
6744 self.orig_loc,
6745 self.buf.as_ptr() as usize,
6746 ))
6747 }
6748 #[doc = "ifindex of the netdev to which the pool belongs.\nMay be reported as 0 if the page pool was allocated for a netdev\nwhich got destroyed already (page pools may outlast their netdevs\nbecause they wait for all memory to be returned).\n"]
6749 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6750 let mut iter = self.clone();
6751 iter.pos = 0;
6752 for attr in iter {
6753 if let OpPagePoolGetDoReply::Ifindex(val) = attr? {
6754 return Ok(val);
6755 }
6756 }
6757 Err(ErrorContext::new_missing(
6758 "OpPagePoolGetDoReply",
6759 "Ifindex",
6760 self.orig_loc,
6761 self.buf.as_ptr() as usize,
6762 ))
6763 }
6764 #[doc = "Id of NAPI using this Page Pool instance."]
6765 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6766 let mut iter = self.clone();
6767 iter.pos = 0;
6768 for attr in iter {
6769 if let OpPagePoolGetDoReply::NapiId(val) = attr? {
6770 return Ok(val);
6771 }
6772 }
6773 Err(ErrorContext::new_missing(
6774 "OpPagePoolGetDoReply",
6775 "NapiId",
6776 self.orig_loc,
6777 self.buf.as_ptr() as usize,
6778 ))
6779 }
6780 #[doc = "Number of outstanding references to this page pool (allocated\nbut yet to be freed pages). Allocated pages may be held in\nsocket receive queues, driver receive ring, page pool recycling\nring, the page pool cache, etc.\n"]
6781 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6782 let mut iter = self.clone();
6783 iter.pos = 0;
6784 for attr in iter {
6785 if let OpPagePoolGetDoReply::Inflight(val) = attr? {
6786 return Ok(val);
6787 }
6788 }
6789 Err(ErrorContext::new_missing(
6790 "OpPagePoolGetDoReply",
6791 "Inflight",
6792 self.orig_loc,
6793 self.buf.as_ptr() as usize,
6794 ))
6795 }
6796 #[doc = "Amount of memory held by inflight pages.\n"]
6797 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6798 let mut iter = self.clone();
6799 iter.pos = 0;
6800 for attr in iter {
6801 if let OpPagePoolGetDoReply::InflightMem(val) = attr? {
6802 return Ok(val);
6803 }
6804 }
6805 Err(ErrorContext::new_missing(
6806 "OpPagePoolGetDoReply",
6807 "InflightMem",
6808 self.orig_loc,
6809 self.buf.as_ptr() as usize,
6810 ))
6811 }
6812 #[doc = "Seconds in CLOCK_BOOTTIME of when Page Pool was detached by\nthe driver. Once detached Page Pool can no longer be used to\nallocate memory.\nPage Pools wait for all the memory allocated from them to be freed\nbefore truly disappearing. \"Detached\" Page Pools cannot be\n\"re-attached\", they are just waiting to disappear.\nAttribute is absent if Page Pool has not been detached, and\ncan still be used to allocate new memory.\n"]
6813 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6814 let mut iter = self.clone();
6815 iter.pos = 0;
6816 for attr in iter {
6817 if let OpPagePoolGetDoReply::DetachTime(val) = attr? {
6818 return Ok(val);
6819 }
6820 }
6821 Err(ErrorContext::new_missing(
6822 "OpPagePoolGetDoReply",
6823 "DetachTime",
6824 self.orig_loc,
6825 self.buf.as_ptr() as usize,
6826 ))
6827 }
6828 #[doc = "ID of the dmabuf this page-pool is attached to."]
6829 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6830 let mut iter = self.clone();
6831 iter.pos = 0;
6832 for attr in iter {
6833 if let OpPagePoolGetDoReply::Dmabuf(val) = attr? {
6834 return Ok(val);
6835 }
6836 }
6837 Err(ErrorContext::new_missing(
6838 "OpPagePoolGetDoReply",
6839 "Dmabuf",
6840 self.orig_loc,
6841 self.buf.as_ptr() as usize,
6842 ))
6843 }
6844 #[doc = "io-uring memory provider information."]
6845 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6846 let mut iter = self.clone();
6847 iter.pos = 0;
6848 for attr in iter {
6849 if let OpPagePoolGetDoReply::IoUring(val) = attr? {
6850 return Ok(val);
6851 }
6852 }
6853 Err(ErrorContext::new_missing(
6854 "OpPagePoolGetDoReply",
6855 "IoUring",
6856 self.orig_loc,
6857 self.buf.as_ptr() as usize,
6858 ))
6859 }
6860}
6861impl OpPagePoolGetDoReply<'_> {
6862 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoReply<'a> {
6863 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6864 IterableOpPagePoolGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
6865 }
6866 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6867 PagePool::attr_from_type(r#type)
6868 }
6869}
6870#[derive(Clone, Copy, Default)]
6871pub struct IterableOpPagePoolGetDoReply<'a> {
6872 buf: &'a [u8],
6873 pos: usize,
6874 orig_loc: usize,
6875}
6876impl<'a> IterableOpPagePoolGetDoReply<'a> {
6877 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6878 Self {
6879 buf,
6880 pos: 0,
6881 orig_loc,
6882 }
6883 }
6884 pub fn get_buf(&self) -> &'a [u8] {
6885 self.buf
6886 }
6887}
6888impl<'a> Iterator for IterableOpPagePoolGetDoReply<'a> {
6889 type Item = Result<OpPagePoolGetDoReply<'a>, ErrorContext>;
6890 fn next(&mut self) -> Option<Self::Item> {
6891 let pos = self.pos;
6892 let mut r#type;
6893 loop {
6894 r#type = None;
6895 if self.buf.len() == self.pos {
6896 return None;
6897 }
6898 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
6899 break;
6900 };
6901 r#type = Some(header.r#type);
6902 let res = match header.r#type {
6903 1u16 => OpPagePoolGetDoReply::Id({
6904 let res = parse_u32(next);
6905 let Some(val) = res else { break };
6906 val
6907 }),
6908 2u16 => OpPagePoolGetDoReply::Ifindex({
6909 let res = parse_u32(next);
6910 let Some(val) = res else { break };
6911 val
6912 }),
6913 3u16 => OpPagePoolGetDoReply::NapiId({
6914 let res = parse_u32(next);
6915 let Some(val) = res else { break };
6916 val
6917 }),
6918 4u16 => OpPagePoolGetDoReply::Inflight({
6919 let res = parse_u32(next);
6920 let Some(val) = res else { break };
6921 val
6922 }),
6923 5u16 => OpPagePoolGetDoReply::InflightMem({
6924 let res = parse_u32(next);
6925 let Some(val) = res else { break };
6926 val
6927 }),
6928 6u16 => OpPagePoolGetDoReply::DetachTime({
6929 let res = parse_u32(next);
6930 let Some(val) = res else { break };
6931 val
6932 }),
6933 7u16 => OpPagePoolGetDoReply::Dmabuf({
6934 let res = parse_u32(next);
6935 let Some(val) = res else { break };
6936 val
6937 }),
6938 8u16 => OpPagePoolGetDoReply::IoUring({
6939 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6940 let Some(val) = res else { break };
6941 val
6942 }),
6943 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
6944 n => continue,
6945 };
6946 return Some(Ok(res));
6947 }
6948 Some(Err(ErrorContext::new(
6949 "OpPagePoolGetDoReply",
6950 r#type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6951 self.orig_loc,
6952 self.buf.as_ptr().wrapping_add(pos) as usize,
6953 )))
6954 }
6955}
6956impl<'a> std::fmt::Debug for IterableOpPagePoolGetDoReply<'_> {
6957 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6958 let mut fmt = f.debug_struct("OpPagePoolGetDoReply");
6959 for attr in self.clone() {
6960 let attr = match attr {
6961 Ok(a) => a,
6962 Err(err) => {
6963 fmt.finish()?;
6964 f.write_str("Err(")?;
6965 err.fmt(f)?;
6966 return f.write_str(")");
6967 }
6968 };
6969 match attr {
6970 OpPagePoolGetDoReply::Id(val) => fmt.field("Id", &val),
6971 OpPagePoolGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
6972 OpPagePoolGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
6973 OpPagePoolGetDoReply::Inflight(val) => fmt.field("Inflight", &val),
6974 OpPagePoolGetDoReply::InflightMem(val) => fmt.field("InflightMem", &val),
6975 OpPagePoolGetDoReply::DetachTime(val) => fmt.field("DetachTime", &val),
6976 OpPagePoolGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6977 OpPagePoolGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
6978 };
6979 }
6980 fmt.finish()
6981 }
6982}
6983impl IterableOpPagePoolGetDoReply<'_> {
6984 pub fn lookup_attr(
6985 &self,
6986 offset: usize,
6987 missing_type: Option<u16>,
6988 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6989 let mut stack = Vec::new();
6990 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6991 if cur == offset + PushBuiltinNfgenmsg::len() {
6992 stack.push(("OpPagePoolGetDoReply", offset));
6993 return (
6994 stack,
6995 missing_type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6996 );
6997 }
6998 if cur > offset || cur + self.buf.len() < offset {
6999 return (stack, None);
7000 }
7001 let mut attrs = self.clone();
7002 let mut last_off = cur + attrs.pos;
7003 let mut missing = None;
7004 while let Some(attr) = attrs.next() {
7005 let Ok(attr) = attr else { break };
7006 match attr {
7007 OpPagePoolGetDoReply::Id(val) => {
7008 if last_off == offset {
7009 stack.push(("Id", last_off));
7010 break;
7011 }
7012 }
7013 OpPagePoolGetDoReply::Ifindex(val) => {
7014 if last_off == offset {
7015 stack.push(("Ifindex", last_off));
7016 break;
7017 }
7018 }
7019 OpPagePoolGetDoReply::NapiId(val) => {
7020 if last_off == offset {
7021 stack.push(("NapiId", last_off));
7022 break;
7023 }
7024 }
7025 OpPagePoolGetDoReply::Inflight(val) => {
7026 if last_off == offset {
7027 stack.push(("Inflight", last_off));
7028 break;
7029 }
7030 }
7031 OpPagePoolGetDoReply::InflightMem(val) => {
7032 if last_off == offset {
7033 stack.push(("InflightMem", last_off));
7034 break;
7035 }
7036 }
7037 OpPagePoolGetDoReply::DetachTime(val) => {
7038 if last_off == offset {
7039 stack.push(("DetachTime", last_off));
7040 break;
7041 }
7042 }
7043 OpPagePoolGetDoReply::Dmabuf(val) => {
7044 if last_off == offset {
7045 stack.push(("Dmabuf", last_off));
7046 break;
7047 }
7048 }
7049 OpPagePoolGetDoReply::IoUring(val) => {
7050 (stack, missing) = val.lookup_attr(offset, missing_type);
7051 if !stack.is_empty() {
7052 break;
7053 }
7054 }
7055 _ => {}
7056 };
7057 last_off = cur + attrs.pos;
7058 }
7059 if !stack.is_empty() {
7060 stack.push(("OpPagePoolGetDoReply", cur));
7061 }
7062 (stack, missing)
7063 }
7064}
7065#[derive(Debug)]
7066pub struct RequestOpPagePoolGetDoRequest<'r> {
7067 request: Request<'r>,
7068}
7069impl<'r> RequestOpPagePoolGetDoRequest<'r> {
7070 pub fn new(mut request: Request<'r>) -> Self {
7071 PushOpPagePoolGetDoRequest::write_header(&mut request.buf_mut());
7072 Self { request: request }
7073 }
7074 pub fn encode(&mut self) -> PushOpPagePoolGetDoRequest<&mut Vec<u8>> {
7075 PushOpPagePoolGetDoRequest::new_without_header(self.request.buf_mut())
7076 }
7077 pub fn into_encoder(self) -> PushOpPagePoolGetDoRequest<RequestBuf<'r>> {
7078 PushOpPagePoolGetDoRequest::new_without_header(self.request.buf)
7079 }
7080 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolGetDoRequest<'buf> {
7081 OpPagePoolGetDoRequest::new(buf)
7082 }
7083}
7084impl NetlinkRequest for RequestOpPagePoolGetDoRequest<'_> {
7085 fn protocol(&self) -> Protocol {
7086 Protocol::Generic("netdev".as_bytes())
7087 }
7088 fn flags(&self) -> u16 {
7089 self.request.flags
7090 }
7091 fn payload(&self) -> &[u8] {
7092 self.request.buf()
7093 }
7094 type ReplyType<'buf> = IterableOpPagePoolGetDoReply<'buf>;
7095 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7096 OpPagePoolGetDoReply::new(buf)
7097 }
7098 fn lookup(
7099 buf: &[u8],
7100 offset: usize,
7101 missing_type: Option<u16>,
7102 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7103 OpPagePoolGetDoRequest::new(buf).lookup_attr(offset, missing_type)
7104 }
7105}
7106#[doc = "Get page pool statistics."]
7107pub struct PushOpPagePoolStatsGetDumpRequest<Prev: Rec> {
7108 pub(crate) prev: Option<Prev>,
7109 pub(crate) header_offset: Option<usize>,
7110}
7111impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpRequest<Prev> {
7112 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7113 self.prev.as_mut().unwrap().as_rec_mut()
7114 }
7115 fn as_rec(&self) -> &Vec<u8> {
7116 self.prev.as_ref().unwrap().as_rec()
7117 }
7118}
7119impl<Prev: Rec> PushOpPagePoolStatsGetDumpRequest<Prev> {
7120 pub fn new(mut prev: Prev) -> Self {
7121 Self::write_header(&mut prev);
7122 Self::new_without_header(prev)
7123 }
7124 fn new_without_header(prev: Prev) -> Self {
7125 Self {
7126 prev: Some(prev),
7127 header_offset: None,
7128 }
7129 }
7130 fn write_header(prev: &mut Prev) {
7131 let mut header = PushBuiltinNfgenmsg::new();
7132 header.set_cmd(9u8);
7133 header.set_version(1u8);
7134 prev.as_rec_mut().extend(header.as_slice());
7135 }
7136 pub fn end_nested(mut self) -> Prev {
7137 let mut prev = self.prev.take().unwrap();
7138 if let Some(header_offset) = &self.header_offset {
7139 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7140 }
7141 prev
7142 }
7143}
7144impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpRequest<Prev> {
7145 fn drop(&mut self) {
7146 if let Some(prev) = &mut self.prev {
7147 if let Some(header_offset) = &self.header_offset {
7148 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7149 }
7150 }
7151 }
7152}
7153#[doc = "Get page pool statistics."]
7154#[derive(Clone)]
7155pub enum OpPagePoolStatsGetDumpRequest {}
7156impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {}
7157impl OpPagePoolStatsGetDumpRequest {
7158 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'a> {
7159 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7160 IterableOpPagePoolStatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
7161 }
7162 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7163 PagePoolStats::attr_from_type(r#type)
7164 }
7165}
7166#[derive(Clone, Copy, Default)]
7167pub struct IterableOpPagePoolStatsGetDumpRequest<'a> {
7168 buf: &'a [u8],
7169 pos: usize,
7170 orig_loc: usize,
7171}
7172impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {
7173 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7174 Self {
7175 buf,
7176 pos: 0,
7177 orig_loc,
7178 }
7179 }
7180 pub fn get_buf(&self) -> &'a [u8] {
7181 self.buf
7182 }
7183}
7184impl<'a> Iterator for IterableOpPagePoolStatsGetDumpRequest<'a> {
7185 type Item = Result<OpPagePoolStatsGetDumpRequest, ErrorContext>;
7186 fn next(&mut self) -> Option<Self::Item> {
7187 let pos = self.pos;
7188 let mut r#type;
7189 loop {
7190 r#type = None;
7191 if self.buf.len() == self.pos {
7192 return None;
7193 }
7194 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7195 break;
7196 };
7197 r#type = Some(header.r#type);
7198 let res = match header.r#type {
7199 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7200 n => continue,
7201 };
7202 return Some(Ok(res));
7203 }
7204 Some(Err(ErrorContext::new(
7205 "OpPagePoolStatsGetDumpRequest",
7206 r#type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7207 self.orig_loc,
7208 self.buf.as_ptr().wrapping_add(pos) as usize,
7209 )))
7210 }
7211}
7212impl std::fmt::Debug for IterableOpPagePoolStatsGetDumpRequest<'_> {
7213 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7214 let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpRequest");
7215 for attr in self.clone() {
7216 let attr = match attr {
7217 Ok(a) => a,
7218 Err(err) => {
7219 fmt.finish()?;
7220 f.write_str("Err(")?;
7221 err.fmt(f)?;
7222 return f.write_str(")");
7223 }
7224 };
7225 match attr {};
7226 }
7227 fmt.finish()
7228 }
7229}
7230impl IterableOpPagePoolStatsGetDumpRequest<'_> {
7231 pub fn lookup_attr(
7232 &self,
7233 offset: usize,
7234 missing_type: Option<u16>,
7235 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7236 let mut stack = Vec::new();
7237 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7238 if cur == offset + PushBuiltinNfgenmsg::len() {
7239 stack.push(("OpPagePoolStatsGetDumpRequest", offset));
7240 return (
7241 stack,
7242 missing_type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7243 );
7244 }
7245 (stack, None)
7246 }
7247}
7248#[doc = "Get page pool statistics."]
7249pub struct PushOpPagePoolStatsGetDumpReply<Prev: Rec> {
7250 pub(crate) prev: Option<Prev>,
7251 pub(crate) header_offset: Option<usize>,
7252}
7253impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpReply<Prev> {
7254 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7255 self.prev.as_mut().unwrap().as_rec_mut()
7256 }
7257 fn as_rec(&self) -> &Vec<u8> {
7258 self.prev.as_ref().unwrap().as_rec()
7259 }
7260}
7261impl<Prev: Rec> PushOpPagePoolStatsGetDumpReply<Prev> {
7262 pub fn new(mut prev: Prev) -> Self {
7263 Self::write_header(&mut prev);
7264 Self::new_without_header(prev)
7265 }
7266 fn new_without_header(prev: Prev) -> Self {
7267 Self {
7268 prev: Some(prev),
7269 header_offset: None,
7270 }
7271 }
7272 fn write_header(prev: &mut Prev) {
7273 let mut header = PushBuiltinNfgenmsg::new();
7274 header.set_cmd(9u8);
7275 header.set_version(1u8);
7276 prev.as_rec_mut().extend(header.as_slice());
7277 }
7278 pub fn end_nested(mut self) -> Prev {
7279 let mut prev = self.prev.take().unwrap();
7280 if let Some(header_offset) = &self.header_offset {
7281 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7282 }
7283 prev
7284 }
7285 #[doc = "Page pool identifying information."]
7286 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7287 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7288 PushPagePoolInfo {
7289 prev: Some(self),
7290 header_offset: Some(header_offset),
7291 }
7292 }
7293 pub fn push_alloc_fast(mut self, value: u32) -> Self {
7294 push_header(self.as_rec_mut(), 8u16, 4 as u16);
7295 self.as_rec_mut().extend(value.to_ne_bytes());
7296 self
7297 }
7298 pub fn push_alloc_slow(mut self, value: u32) -> Self {
7299 push_header(self.as_rec_mut(), 9u16, 4 as u16);
7300 self.as_rec_mut().extend(value.to_ne_bytes());
7301 self
7302 }
7303 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
7304 push_header(self.as_rec_mut(), 10u16, 4 as u16);
7305 self.as_rec_mut().extend(value.to_ne_bytes());
7306 self
7307 }
7308 pub fn push_alloc_empty(mut self, value: u32) -> Self {
7309 push_header(self.as_rec_mut(), 11u16, 4 as u16);
7310 self.as_rec_mut().extend(value.to_ne_bytes());
7311 self
7312 }
7313 pub fn push_alloc_refill(mut self, value: u32) -> Self {
7314 push_header(self.as_rec_mut(), 12u16, 4 as u16);
7315 self.as_rec_mut().extend(value.to_ne_bytes());
7316 self
7317 }
7318 pub fn push_alloc_waive(mut self, value: u32) -> Self {
7319 push_header(self.as_rec_mut(), 13u16, 4 as u16);
7320 self.as_rec_mut().extend(value.to_ne_bytes());
7321 self
7322 }
7323 pub fn push_recycle_cached(mut self, value: u32) -> Self {
7324 push_header(self.as_rec_mut(), 14u16, 4 as u16);
7325 self.as_rec_mut().extend(value.to_ne_bytes());
7326 self
7327 }
7328 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
7329 push_header(self.as_rec_mut(), 15u16, 4 as u16);
7330 self.as_rec_mut().extend(value.to_ne_bytes());
7331 self
7332 }
7333 pub fn push_recycle_ring(mut self, value: u32) -> Self {
7334 push_header(self.as_rec_mut(), 16u16, 4 as u16);
7335 self.as_rec_mut().extend(value.to_ne_bytes());
7336 self
7337 }
7338 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
7339 push_header(self.as_rec_mut(), 17u16, 4 as u16);
7340 self.as_rec_mut().extend(value.to_ne_bytes());
7341 self
7342 }
7343 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
7344 push_header(self.as_rec_mut(), 18u16, 4 as u16);
7345 self.as_rec_mut().extend(value.to_ne_bytes());
7346 self
7347 }
7348}
7349impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpReply<Prev> {
7350 fn drop(&mut self) {
7351 if let Some(prev) = &mut self.prev {
7352 if let Some(header_offset) = &self.header_offset {
7353 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7354 }
7355 }
7356 }
7357}
7358#[doc = "Get page pool statistics."]
7359#[derive(Clone)]
7360pub enum OpPagePoolStatsGetDumpReply<'a> {
7361 #[doc = "Page pool identifying information."]
7362 Info(IterablePagePoolInfo<'a>),
7363 AllocFast(u32),
7364 AllocSlow(u32),
7365 AllocSlowHighOrder(u32),
7366 AllocEmpty(u32),
7367 AllocRefill(u32),
7368 AllocWaive(u32),
7369 RecycleCached(u32),
7370 RecycleCacheFull(u32),
7371 RecycleRing(u32),
7372 RecycleRingFull(u32),
7373 RecycleReleasedRefcnt(u32),
7374}
7375impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7376 #[doc = "Page pool identifying information."]
7377 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7378 let mut iter = self.clone();
7379 iter.pos = 0;
7380 for attr in iter {
7381 if let OpPagePoolStatsGetDumpReply::Info(val) = attr? {
7382 return Ok(val);
7383 }
7384 }
7385 Err(ErrorContext::new_missing(
7386 "OpPagePoolStatsGetDumpReply",
7387 "Info",
7388 self.orig_loc,
7389 self.buf.as_ptr() as usize,
7390 ))
7391 }
7392 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
7393 let mut iter = self.clone();
7394 iter.pos = 0;
7395 for attr in iter {
7396 if let OpPagePoolStatsGetDumpReply::AllocFast(val) = attr? {
7397 return Ok(val);
7398 }
7399 }
7400 Err(ErrorContext::new_missing(
7401 "OpPagePoolStatsGetDumpReply",
7402 "AllocFast",
7403 self.orig_loc,
7404 self.buf.as_ptr() as usize,
7405 ))
7406 }
7407 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
7408 let mut iter = self.clone();
7409 iter.pos = 0;
7410 for attr in iter {
7411 if let OpPagePoolStatsGetDumpReply::AllocSlow(val) = attr? {
7412 return Ok(val);
7413 }
7414 }
7415 Err(ErrorContext::new_missing(
7416 "OpPagePoolStatsGetDumpReply",
7417 "AllocSlow",
7418 self.orig_loc,
7419 self.buf.as_ptr() as usize,
7420 ))
7421 }
7422 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
7423 let mut iter = self.clone();
7424 iter.pos = 0;
7425 for attr in iter {
7426 if let OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) = attr? {
7427 return Ok(val);
7428 }
7429 }
7430 Err(ErrorContext::new_missing(
7431 "OpPagePoolStatsGetDumpReply",
7432 "AllocSlowHighOrder",
7433 self.orig_loc,
7434 self.buf.as_ptr() as usize,
7435 ))
7436 }
7437 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
7438 let mut iter = self.clone();
7439 iter.pos = 0;
7440 for attr in iter {
7441 if let OpPagePoolStatsGetDumpReply::AllocEmpty(val) = attr? {
7442 return Ok(val);
7443 }
7444 }
7445 Err(ErrorContext::new_missing(
7446 "OpPagePoolStatsGetDumpReply",
7447 "AllocEmpty",
7448 self.orig_loc,
7449 self.buf.as_ptr() as usize,
7450 ))
7451 }
7452 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
7453 let mut iter = self.clone();
7454 iter.pos = 0;
7455 for attr in iter {
7456 if let OpPagePoolStatsGetDumpReply::AllocRefill(val) = attr? {
7457 return Ok(val);
7458 }
7459 }
7460 Err(ErrorContext::new_missing(
7461 "OpPagePoolStatsGetDumpReply",
7462 "AllocRefill",
7463 self.orig_loc,
7464 self.buf.as_ptr() as usize,
7465 ))
7466 }
7467 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
7468 let mut iter = self.clone();
7469 iter.pos = 0;
7470 for attr in iter {
7471 if let OpPagePoolStatsGetDumpReply::AllocWaive(val) = attr? {
7472 return Ok(val);
7473 }
7474 }
7475 Err(ErrorContext::new_missing(
7476 "OpPagePoolStatsGetDumpReply",
7477 "AllocWaive",
7478 self.orig_loc,
7479 self.buf.as_ptr() as usize,
7480 ))
7481 }
7482 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
7483 let mut iter = self.clone();
7484 iter.pos = 0;
7485 for attr in iter {
7486 if let OpPagePoolStatsGetDumpReply::RecycleCached(val) = attr? {
7487 return Ok(val);
7488 }
7489 }
7490 Err(ErrorContext::new_missing(
7491 "OpPagePoolStatsGetDumpReply",
7492 "RecycleCached",
7493 self.orig_loc,
7494 self.buf.as_ptr() as usize,
7495 ))
7496 }
7497 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
7498 let mut iter = self.clone();
7499 iter.pos = 0;
7500 for attr in iter {
7501 if let OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) = attr? {
7502 return Ok(val);
7503 }
7504 }
7505 Err(ErrorContext::new_missing(
7506 "OpPagePoolStatsGetDumpReply",
7507 "RecycleCacheFull",
7508 self.orig_loc,
7509 self.buf.as_ptr() as usize,
7510 ))
7511 }
7512 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
7513 let mut iter = self.clone();
7514 iter.pos = 0;
7515 for attr in iter {
7516 if let OpPagePoolStatsGetDumpReply::RecycleRing(val) = attr? {
7517 return Ok(val);
7518 }
7519 }
7520 Err(ErrorContext::new_missing(
7521 "OpPagePoolStatsGetDumpReply",
7522 "RecycleRing",
7523 self.orig_loc,
7524 self.buf.as_ptr() as usize,
7525 ))
7526 }
7527 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
7528 let mut iter = self.clone();
7529 iter.pos = 0;
7530 for attr in iter {
7531 if let OpPagePoolStatsGetDumpReply::RecycleRingFull(val) = attr? {
7532 return Ok(val);
7533 }
7534 }
7535 Err(ErrorContext::new_missing(
7536 "OpPagePoolStatsGetDumpReply",
7537 "RecycleRingFull",
7538 self.orig_loc,
7539 self.buf.as_ptr() as usize,
7540 ))
7541 }
7542 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
7543 let mut iter = self.clone();
7544 iter.pos = 0;
7545 for attr in iter {
7546 if let OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) = attr? {
7547 return Ok(val);
7548 }
7549 }
7550 Err(ErrorContext::new_missing(
7551 "OpPagePoolStatsGetDumpReply",
7552 "RecycleReleasedRefcnt",
7553 self.orig_loc,
7554 self.buf.as_ptr() as usize,
7555 ))
7556 }
7557}
7558impl OpPagePoolStatsGetDumpReply<'_> {
7559 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpReply<'a> {
7560 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7561 IterableOpPagePoolStatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
7562 }
7563 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7564 PagePoolStats::attr_from_type(r#type)
7565 }
7566}
7567#[derive(Clone, Copy, Default)]
7568pub struct IterableOpPagePoolStatsGetDumpReply<'a> {
7569 buf: &'a [u8],
7570 pos: usize,
7571 orig_loc: usize,
7572}
7573impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7574 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7575 Self {
7576 buf,
7577 pos: 0,
7578 orig_loc,
7579 }
7580 }
7581 pub fn get_buf(&self) -> &'a [u8] {
7582 self.buf
7583 }
7584}
7585impl<'a> Iterator for IterableOpPagePoolStatsGetDumpReply<'a> {
7586 type Item = Result<OpPagePoolStatsGetDumpReply<'a>, ErrorContext>;
7587 fn next(&mut self) -> Option<Self::Item> {
7588 let pos = self.pos;
7589 let mut r#type;
7590 loop {
7591 r#type = None;
7592 if self.buf.len() == self.pos {
7593 return None;
7594 }
7595 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7596 break;
7597 };
7598 r#type = Some(header.r#type);
7599 let res = match header.r#type {
7600 1u16 => OpPagePoolStatsGetDumpReply::Info({
7601 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7602 let Some(val) = res else { break };
7603 val
7604 }),
7605 8u16 => OpPagePoolStatsGetDumpReply::AllocFast({
7606 let res = parse_u32(next);
7607 let Some(val) = res else { break };
7608 val
7609 }),
7610 9u16 => OpPagePoolStatsGetDumpReply::AllocSlow({
7611 let res = parse_u32(next);
7612 let Some(val) = res else { break };
7613 val
7614 }),
7615 10u16 => OpPagePoolStatsGetDumpReply::AllocSlowHighOrder({
7616 let res = parse_u32(next);
7617 let Some(val) = res else { break };
7618 val
7619 }),
7620 11u16 => OpPagePoolStatsGetDumpReply::AllocEmpty({
7621 let res = parse_u32(next);
7622 let Some(val) = res else { break };
7623 val
7624 }),
7625 12u16 => OpPagePoolStatsGetDumpReply::AllocRefill({
7626 let res = parse_u32(next);
7627 let Some(val) = res else { break };
7628 val
7629 }),
7630 13u16 => OpPagePoolStatsGetDumpReply::AllocWaive({
7631 let res = parse_u32(next);
7632 let Some(val) = res else { break };
7633 val
7634 }),
7635 14u16 => OpPagePoolStatsGetDumpReply::RecycleCached({
7636 let res = parse_u32(next);
7637 let Some(val) = res else { break };
7638 val
7639 }),
7640 15u16 => OpPagePoolStatsGetDumpReply::RecycleCacheFull({
7641 let res = parse_u32(next);
7642 let Some(val) = res else { break };
7643 val
7644 }),
7645 16u16 => OpPagePoolStatsGetDumpReply::RecycleRing({
7646 let res = parse_u32(next);
7647 let Some(val) = res else { break };
7648 val
7649 }),
7650 17u16 => OpPagePoolStatsGetDumpReply::RecycleRingFull({
7651 let res = parse_u32(next);
7652 let Some(val) = res else { break };
7653 val
7654 }),
7655 18u16 => OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt({
7656 let res = parse_u32(next);
7657 let Some(val) = res else { break };
7658 val
7659 }),
7660 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7661 n => continue,
7662 };
7663 return Some(Ok(res));
7664 }
7665 Some(Err(ErrorContext::new(
7666 "OpPagePoolStatsGetDumpReply",
7667 r#type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7668 self.orig_loc,
7669 self.buf.as_ptr().wrapping_add(pos) as usize,
7670 )))
7671 }
7672}
7673impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDumpReply<'_> {
7674 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7675 let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpReply");
7676 for attr in self.clone() {
7677 let attr = match attr {
7678 Ok(a) => a,
7679 Err(err) => {
7680 fmt.finish()?;
7681 f.write_str("Err(")?;
7682 err.fmt(f)?;
7683 return f.write_str(")");
7684 }
7685 };
7686 match attr {
7687 OpPagePoolStatsGetDumpReply::Info(val) => fmt.field("Info", &val),
7688 OpPagePoolStatsGetDumpReply::AllocFast(val) => fmt.field("AllocFast", &val),
7689 OpPagePoolStatsGetDumpReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
7690 OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7691 fmt.field("AllocSlowHighOrder", &val)
7692 }
7693 OpPagePoolStatsGetDumpReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
7694 OpPagePoolStatsGetDumpReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
7695 OpPagePoolStatsGetDumpReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
7696 OpPagePoolStatsGetDumpReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
7697 OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7698 fmt.field("RecycleCacheFull", &val)
7699 }
7700 OpPagePoolStatsGetDumpReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
7701 OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7702 fmt.field("RecycleRingFull", &val)
7703 }
7704 OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7705 fmt.field("RecycleReleasedRefcnt", &val)
7706 }
7707 };
7708 }
7709 fmt.finish()
7710 }
7711}
7712impl IterableOpPagePoolStatsGetDumpReply<'_> {
7713 pub fn lookup_attr(
7714 &self,
7715 offset: usize,
7716 missing_type: Option<u16>,
7717 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7718 let mut stack = Vec::new();
7719 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7720 if cur == offset + PushBuiltinNfgenmsg::len() {
7721 stack.push(("OpPagePoolStatsGetDumpReply", offset));
7722 return (
7723 stack,
7724 missing_type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7725 );
7726 }
7727 if cur > offset || cur + self.buf.len() < offset {
7728 return (stack, None);
7729 }
7730 let mut attrs = self.clone();
7731 let mut last_off = cur + attrs.pos;
7732 let mut missing = None;
7733 while let Some(attr) = attrs.next() {
7734 let Ok(attr) = attr else { break };
7735 match attr {
7736 OpPagePoolStatsGetDumpReply::Info(val) => {
7737 (stack, missing) = val.lookup_attr(offset, missing_type);
7738 if !stack.is_empty() {
7739 break;
7740 }
7741 }
7742 OpPagePoolStatsGetDumpReply::AllocFast(val) => {
7743 if last_off == offset {
7744 stack.push(("AllocFast", last_off));
7745 break;
7746 }
7747 }
7748 OpPagePoolStatsGetDumpReply::AllocSlow(val) => {
7749 if last_off == offset {
7750 stack.push(("AllocSlow", last_off));
7751 break;
7752 }
7753 }
7754 OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7755 if last_off == offset {
7756 stack.push(("AllocSlowHighOrder", last_off));
7757 break;
7758 }
7759 }
7760 OpPagePoolStatsGetDumpReply::AllocEmpty(val) => {
7761 if last_off == offset {
7762 stack.push(("AllocEmpty", last_off));
7763 break;
7764 }
7765 }
7766 OpPagePoolStatsGetDumpReply::AllocRefill(val) => {
7767 if last_off == offset {
7768 stack.push(("AllocRefill", last_off));
7769 break;
7770 }
7771 }
7772 OpPagePoolStatsGetDumpReply::AllocWaive(val) => {
7773 if last_off == offset {
7774 stack.push(("AllocWaive", last_off));
7775 break;
7776 }
7777 }
7778 OpPagePoolStatsGetDumpReply::RecycleCached(val) => {
7779 if last_off == offset {
7780 stack.push(("RecycleCached", last_off));
7781 break;
7782 }
7783 }
7784 OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7785 if last_off == offset {
7786 stack.push(("RecycleCacheFull", last_off));
7787 break;
7788 }
7789 }
7790 OpPagePoolStatsGetDumpReply::RecycleRing(val) => {
7791 if last_off == offset {
7792 stack.push(("RecycleRing", last_off));
7793 break;
7794 }
7795 }
7796 OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7797 if last_off == offset {
7798 stack.push(("RecycleRingFull", last_off));
7799 break;
7800 }
7801 }
7802 OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7803 if last_off == offset {
7804 stack.push(("RecycleReleasedRefcnt", last_off));
7805 break;
7806 }
7807 }
7808 _ => {}
7809 };
7810 last_off = cur + attrs.pos;
7811 }
7812 if !stack.is_empty() {
7813 stack.push(("OpPagePoolStatsGetDumpReply", cur));
7814 }
7815 (stack, missing)
7816 }
7817}
7818#[derive(Debug)]
7819pub struct RequestOpPagePoolStatsGetDumpRequest<'r> {
7820 request: Request<'r>,
7821}
7822impl<'r> RequestOpPagePoolStatsGetDumpRequest<'r> {
7823 pub fn new(mut request: Request<'r>) -> Self {
7824 PushOpPagePoolStatsGetDumpRequest::write_header(&mut request.buf_mut());
7825 Self {
7826 request: request.set_dump(),
7827 }
7828 }
7829 pub fn encode(&mut self) -> PushOpPagePoolStatsGetDumpRequest<&mut Vec<u8>> {
7830 PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf_mut())
7831 }
7832 pub fn into_encoder(self) -> PushOpPagePoolStatsGetDumpRequest<RequestBuf<'r>> {
7833 PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf)
7834 }
7835 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'buf> {
7836 OpPagePoolStatsGetDumpRequest::new(buf)
7837 }
7838}
7839impl NetlinkRequest for RequestOpPagePoolStatsGetDumpRequest<'_> {
7840 fn protocol(&self) -> Protocol {
7841 Protocol::Generic("netdev".as_bytes())
7842 }
7843 fn flags(&self) -> u16 {
7844 self.request.flags
7845 }
7846 fn payload(&self) -> &[u8] {
7847 self.request.buf()
7848 }
7849 type ReplyType<'buf> = IterableOpPagePoolStatsGetDumpReply<'buf>;
7850 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7851 OpPagePoolStatsGetDumpReply::new(buf)
7852 }
7853 fn lookup(
7854 buf: &[u8],
7855 offset: usize,
7856 missing_type: Option<u16>,
7857 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7858 OpPagePoolStatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
7859 }
7860}
7861#[doc = "Get page pool statistics."]
7862pub struct PushOpPagePoolStatsGetDoRequest<Prev: Rec> {
7863 pub(crate) prev: Option<Prev>,
7864 pub(crate) header_offset: Option<usize>,
7865}
7866impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoRequest<Prev> {
7867 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7868 self.prev.as_mut().unwrap().as_rec_mut()
7869 }
7870 fn as_rec(&self) -> &Vec<u8> {
7871 self.prev.as_ref().unwrap().as_rec()
7872 }
7873}
7874impl<Prev: Rec> PushOpPagePoolStatsGetDoRequest<Prev> {
7875 pub fn new(mut prev: Prev) -> Self {
7876 Self::write_header(&mut prev);
7877 Self::new_without_header(prev)
7878 }
7879 fn new_without_header(prev: Prev) -> Self {
7880 Self {
7881 prev: Some(prev),
7882 header_offset: None,
7883 }
7884 }
7885 fn write_header(prev: &mut Prev) {
7886 let mut header = PushBuiltinNfgenmsg::new();
7887 header.set_cmd(9u8);
7888 header.set_version(1u8);
7889 prev.as_rec_mut().extend(header.as_slice());
7890 }
7891 pub fn end_nested(mut self) -> Prev {
7892 let mut prev = self.prev.take().unwrap();
7893 if let Some(header_offset) = &self.header_offset {
7894 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7895 }
7896 prev
7897 }
7898 #[doc = "Page pool identifying information."]
7899 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7900 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7901 PushPagePoolInfo {
7902 prev: Some(self),
7903 header_offset: Some(header_offset),
7904 }
7905 }
7906}
7907impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoRequest<Prev> {
7908 fn drop(&mut self) {
7909 if let Some(prev) = &mut self.prev {
7910 if let Some(header_offset) = &self.header_offset {
7911 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7912 }
7913 }
7914 }
7915}
7916#[doc = "Get page pool statistics."]
7917#[derive(Clone)]
7918pub enum OpPagePoolStatsGetDoRequest<'a> {
7919 #[doc = "Page pool identifying information."]
7920 Info(IterablePagePoolInfo<'a>),
7921}
7922impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7923 #[doc = "Page pool identifying information."]
7924 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7925 let mut iter = self.clone();
7926 iter.pos = 0;
7927 for attr in iter {
7928 if let OpPagePoolStatsGetDoRequest::Info(val) = attr? {
7929 return Ok(val);
7930 }
7931 }
7932 Err(ErrorContext::new_missing(
7933 "OpPagePoolStatsGetDoRequest",
7934 "Info",
7935 self.orig_loc,
7936 self.buf.as_ptr() as usize,
7937 ))
7938 }
7939}
7940impl OpPagePoolStatsGetDoRequest<'_> {
7941 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoRequest<'a> {
7942 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7943 IterableOpPagePoolStatsGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
7944 }
7945 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7946 PagePoolStats::attr_from_type(r#type)
7947 }
7948}
7949#[derive(Clone, Copy, Default)]
7950pub struct IterableOpPagePoolStatsGetDoRequest<'a> {
7951 buf: &'a [u8],
7952 pos: usize,
7953 orig_loc: usize,
7954}
7955impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7956 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7957 Self {
7958 buf,
7959 pos: 0,
7960 orig_loc,
7961 }
7962 }
7963 pub fn get_buf(&self) -> &'a [u8] {
7964 self.buf
7965 }
7966}
7967impl<'a> Iterator for IterableOpPagePoolStatsGetDoRequest<'a> {
7968 type Item = Result<OpPagePoolStatsGetDoRequest<'a>, ErrorContext>;
7969 fn next(&mut self) -> Option<Self::Item> {
7970 let pos = self.pos;
7971 let mut r#type;
7972 loop {
7973 r#type = None;
7974 if self.buf.len() == self.pos {
7975 return None;
7976 }
7977 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
7978 break;
7979 };
7980 r#type = Some(header.r#type);
7981 let res = match header.r#type {
7982 1u16 => OpPagePoolStatsGetDoRequest::Info({
7983 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7984 let Some(val) = res else { break };
7985 val
7986 }),
7987 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
7988 n => continue,
7989 };
7990 return Some(Ok(res));
7991 }
7992 Some(Err(ErrorContext::new(
7993 "OpPagePoolStatsGetDoRequest",
7994 r#type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7995 self.orig_loc,
7996 self.buf.as_ptr().wrapping_add(pos) as usize,
7997 )))
7998 }
7999}
8000impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoRequest<'_> {
8001 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8002 let mut fmt = f.debug_struct("OpPagePoolStatsGetDoRequest");
8003 for attr in self.clone() {
8004 let attr = match attr {
8005 Ok(a) => a,
8006 Err(err) => {
8007 fmt.finish()?;
8008 f.write_str("Err(")?;
8009 err.fmt(f)?;
8010 return f.write_str(")");
8011 }
8012 };
8013 match attr {
8014 OpPagePoolStatsGetDoRequest::Info(val) => fmt.field("Info", &val),
8015 };
8016 }
8017 fmt.finish()
8018 }
8019}
8020impl IterableOpPagePoolStatsGetDoRequest<'_> {
8021 pub fn lookup_attr(
8022 &self,
8023 offset: usize,
8024 missing_type: Option<u16>,
8025 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8026 let mut stack = Vec::new();
8027 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8028 if cur == offset + PushBuiltinNfgenmsg::len() {
8029 stack.push(("OpPagePoolStatsGetDoRequest", offset));
8030 return (
8031 stack,
8032 missing_type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
8033 );
8034 }
8035 if cur > offset || cur + self.buf.len() < offset {
8036 return (stack, None);
8037 }
8038 let mut attrs = self.clone();
8039 let mut last_off = cur + attrs.pos;
8040 let mut missing = None;
8041 while let Some(attr) = attrs.next() {
8042 let Ok(attr) = attr else { break };
8043 match attr {
8044 OpPagePoolStatsGetDoRequest::Info(val) => {
8045 (stack, missing) = val.lookup_attr(offset, missing_type);
8046 if !stack.is_empty() {
8047 break;
8048 }
8049 }
8050 _ => {}
8051 };
8052 last_off = cur + attrs.pos;
8053 }
8054 if !stack.is_empty() {
8055 stack.push(("OpPagePoolStatsGetDoRequest", cur));
8056 }
8057 (stack, missing)
8058 }
8059}
8060#[doc = "Get page pool statistics."]
8061pub struct PushOpPagePoolStatsGetDoReply<Prev: Rec> {
8062 pub(crate) prev: Option<Prev>,
8063 pub(crate) header_offset: Option<usize>,
8064}
8065impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoReply<Prev> {
8066 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8067 self.prev.as_mut().unwrap().as_rec_mut()
8068 }
8069 fn as_rec(&self) -> &Vec<u8> {
8070 self.prev.as_ref().unwrap().as_rec()
8071 }
8072}
8073impl<Prev: Rec> PushOpPagePoolStatsGetDoReply<Prev> {
8074 pub fn new(mut prev: Prev) -> Self {
8075 Self::write_header(&mut prev);
8076 Self::new_without_header(prev)
8077 }
8078 fn new_without_header(prev: Prev) -> Self {
8079 Self {
8080 prev: Some(prev),
8081 header_offset: None,
8082 }
8083 }
8084 fn write_header(prev: &mut Prev) {
8085 let mut header = PushBuiltinNfgenmsg::new();
8086 header.set_cmd(9u8);
8087 header.set_version(1u8);
8088 prev.as_rec_mut().extend(header.as_slice());
8089 }
8090 pub fn end_nested(mut self) -> Prev {
8091 let mut prev = self.prev.take().unwrap();
8092 if let Some(header_offset) = &self.header_offset {
8093 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8094 }
8095 prev
8096 }
8097 #[doc = "Page pool identifying information."]
8098 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
8099 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
8100 PushPagePoolInfo {
8101 prev: Some(self),
8102 header_offset: Some(header_offset),
8103 }
8104 }
8105 pub fn push_alloc_fast(mut self, value: u32) -> Self {
8106 push_header(self.as_rec_mut(), 8u16, 4 as u16);
8107 self.as_rec_mut().extend(value.to_ne_bytes());
8108 self
8109 }
8110 pub fn push_alloc_slow(mut self, value: u32) -> Self {
8111 push_header(self.as_rec_mut(), 9u16, 4 as u16);
8112 self.as_rec_mut().extend(value.to_ne_bytes());
8113 self
8114 }
8115 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
8116 push_header(self.as_rec_mut(), 10u16, 4 as u16);
8117 self.as_rec_mut().extend(value.to_ne_bytes());
8118 self
8119 }
8120 pub fn push_alloc_empty(mut self, value: u32) -> Self {
8121 push_header(self.as_rec_mut(), 11u16, 4 as u16);
8122 self.as_rec_mut().extend(value.to_ne_bytes());
8123 self
8124 }
8125 pub fn push_alloc_refill(mut self, value: u32) -> Self {
8126 push_header(self.as_rec_mut(), 12u16, 4 as u16);
8127 self.as_rec_mut().extend(value.to_ne_bytes());
8128 self
8129 }
8130 pub fn push_alloc_waive(mut self, value: u32) -> Self {
8131 push_header(self.as_rec_mut(), 13u16, 4 as u16);
8132 self.as_rec_mut().extend(value.to_ne_bytes());
8133 self
8134 }
8135 pub fn push_recycle_cached(mut self, value: u32) -> Self {
8136 push_header(self.as_rec_mut(), 14u16, 4 as u16);
8137 self.as_rec_mut().extend(value.to_ne_bytes());
8138 self
8139 }
8140 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
8141 push_header(self.as_rec_mut(), 15u16, 4 as u16);
8142 self.as_rec_mut().extend(value.to_ne_bytes());
8143 self
8144 }
8145 pub fn push_recycle_ring(mut self, value: u32) -> Self {
8146 push_header(self.as_rec_mut(), 16u16, 4 as u16);
8147 self.as_rec_mut().extend(value.to_ne_bytes());
8148 self
8149 }
8150 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
8151 push_header(self.as_rec_mut(), 17u16, 4 as u16);
8152 self.as_rec_mut().extend(value.to_ne_bytes());
8153 self
8154 }
8155 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
8156 push_header(self.as_rec_mut(), 18u16, 4 as u16);
8157 self.as_rec_mut().extend(value.to_ne_bytes());
8158 self
8159 }
8160}
8161impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoReply<Prev> {
8162 fn drop(&mut self) {
8163 if let Some(prev) = &mut self.prev {
8164 if let Some(header_offset) = &self.header_offset {
8165 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8166 }
8167 }
8168 }
8169}
8170#[doc = "Get page pool statistics."]
8171#[derive(Clone)]
8172pub enum OpPagePoolStatsGetDoReply<'a> {
8173 #[doc = "Page pool identifying information."]
8174 Info(IterablePagePoolInfo<'a>),
8175 AllocFast(u32),
8176 AllocSlow(u32),
8177 AllocSlowHighOrder(u32),
8178 AllocEmpty(u32),
8179 AllocRefill(u32),
8180 AllocWaive(u32),
8181 RecycleCached(u32),
8182 RecycleCacheFull(u32),
8183 RecycleRing(u32),
8184 RecycleRingFull(u32),
8185 RecycleReleasedRefcnt(u32),
8186}
8187impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8188 #[doc = "Page pool identifying information."]
8189 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
8190 let mut iter = self.clone();
8191 iter.pos = 0;
8192 for attr in iter {
8193 if let OpPagePoolStatsGetDoReply::Info(val) = attr? {
8194 return Ok(val);
8195 }
8196 }
8197 Err(ErrorContext::new_missing(
8198 "OpPagePoolStatsGetDoReply",
8199 "Info",
8200 self.orig_loc,
8201 self.buf.as_ptr() as usize,
8202 ))
8203 }
8204 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
8205 let mut iter = self.clone();
8206 iter.pos = 0;
8207 for attr in iter {
8208 if let OpPagePoolStatsGetDoReply::AllocFast(val) = attr? {
8209 return Ok(val);
8210 }
8211 }
8212 Err(ErrorContext::new_missing(
8213 "OpPagePoolStatsGetDoReply",
8214 "AllocFast",
8215 self.orig_loc,
8216 self.buf.as_ptr() as usize,
8217 ))
8218 }
8219 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
8220 let mut iter = self.clone();
8221 iter.pos = 0;
8222 for attr in iter {
8223 if let OpPagePoolStatsGetDoReply::AllocSlow(val) = attr? {
8224 return Ok(val);
8225 }
8226 }
8227 Err(ErrorContext::new_missing(
8228 "OpPagePoolStatsGetDoReply",
8229 "AllocSlow",
8230 self.orig_loc,
8231 self.buf.as_ptr() as usize,
8232 ))
8233 }
8234 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
8235 let mut iter = self.clone();
8236 iter.pos = 0;
8237 for attr in iter {
8238 if let OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) = attr? {
8239 return Ok(val);
8240 }
8241 }
8242 Err(ErrorContext::new_missing(
8243 "OpPagePoolStatsGetDoReply",
8244 "AllocSlowHighOrder",
8245 self.orig_loc,
8246 self.buf.as_ptr() as usize,
8247 ))
8248 }
8249 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
8250 let mut iter = self.clone();
8251 iter.pos = 0;
8252 for attr in iter {
8253 if let OpPagePoolStatsGetDoReply::AllocEmpty(val) = attr? {
8254 return Ok(val);
8255 }
8256 }
8257 Err(ErrorContext::new_missing(
8258 "OpPagePoolStatsGetDoReply",
8259 "AllocEmpty",
8260 self.orig_loc,
8261 self.buf.as_ptr() as usize,
8262 ))
8263 }
8264 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
8265 let mut iter = self.clone();
8266 iter.pos = 0;
8267 for attr in iter {
8268 if let OpPagePoolStatsGetDoReply::AllocRefill(val) = attr? {
8269 return Ok(val);
8270 }
8271 }
8272 Err(ErrorContext::new_missing(
8273 "OpPagePoolStatsGetDoReply",
8274 "AllocRefill",
8275 self.orig_loc,
8276 self.buf.as_ptr() as usize,
8277 ))
8278 }
8279 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
8280 let mut iter = self.clone();
8281 iter.pos = 0;
8282 for attr in iter {
8283 if let OpPagePoolStatsGetDoReply::AllocWaive(val) = attr? {
8284 return Ok(val);
8285 }
8286 }
8287 Err(ErrorContext::new_missing(
8288 "OpPagePoolStatsGetDoReply",
8289 "AllocWaive",
8290 self.orig_loc,
8291 self.buf.as_ptr() as usize,
8292 ))
8293 }
8294 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
8295 let mut iter = self.clone();
8296 iter.pos = 0;
8297 for attr in iter {
8298 if let OpPagePoolStatsGetDoReply::RecycleCached(val) = attr? {
8299 return Ok(val);
8300 }
8301 }
8302 Err(ErrorContext::new_missing(
8303 "OpPagePoolStatsGetDoReply",
8304 "RecycleCached",
8305 self.orig_loc,
8306 self.buf.as_ptr() as usize,
8307 ))
8308 }
8309 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
8310 let mut iter = self.clone();
8311 iter.pos = 0;
8312 for attr in iter {
8313 if let OpPagePoolStatsGetDoReply::RecycleCacheFull(val) = attr? {
8314 return Ok(val);
8315 }
8316 }
8317 Err(ErrorContext::new_missing(
8318 "OpPagePoolStatsGetDoReply",
8319 "RecycleCacheFull",
8320 self.orig_loc,
8321 self.buf.as_ptr() as usize,
8322 ))
8323 }
8324 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
8325 let mut iter = self.clone();
8326 iter.pos = 0;
8327 for attr in iter {
8328 if let OpPagePoolStatsGetDoReply::RecycleRing(val) = attr? {
8329 return Ok(val);
8330 }
8331 }
8332 Err(ErrorContext::new_missing(
8333 "OpPagePoolStatsGetDoReply",
8334 "RecycleRing",
8335 self.orig_loc,
8336 self.buf.as_ptr() as usize,
8337 ))
8338 }
8339 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
8340 let mut iter = self.clone();
8341 iter.pos = 0;
8342 for attr in iter {
8343 if let OpPagePoolStatsGetDoReply::RecycleRingFull(val) = attr? {
8344 return Ok(val);
8345 }
8346 }
8347 Err(ErrorContext::new_missing(
8348 "OpPagePoolStatsGetDoReply",
8349 "RecycleRingFull",
8350 self.orig_loc,
8351 self.buf.as_ptr() as usize,
8352 ))
8353 }
8354 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
8355 let mut iter = self.clone();
8356 iter.pos = 0;
8357 for attr in iter {
8358 if let OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) = attr? {
8359 return Ok(val);
8360 }
8361 }
8362 Err(ErrorContext::new_missing(
8363 "OpPagePoolStatsGetDoReply",
8364 "RecycleReleasedRefcnt",
8365 self.orig_loc,
8366 self.buf.as_ptr() as usize,
8367 ))
8368 }
8369}
8370impl OpPagePoolStatsGetDoReply<'_> {
8371 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoReply<'a> {
8372 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8373 IterableOpPagePoolStatsGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
8374 }
8375 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8376 PagePoolStats::attr_from_type(r#type)
8377 }
8378}
8379#[derive(Clone, Copy, Default)]
8380pub struct IterableOpPagePoolStatsGetDoReply<'a> {
8381 buf: &'a [u8],
8382 pos: usize,
8383 orig_loc: usize,
8384}
8385impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8386 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8387 Self {
8388 buf,
8389 pos: 0,
8390 orig_loc,
8391 }
8392 }
8393 pub fn get_buf(&self) -> &'a [u8] {
8394 self.buf
8395 }
8396}
8397impl<'a> Iterator for IterableOpPagePoolStatsGetDoReply<'a> {
8398 type Item = Result<OpPagePoolStatsGetDoReply<'a>, ErrorContext>;
8399 fn next(&mut self) -> Option<Self::Item> {
8400 let pos = self.pos;
8401 let mut r#type;
8402 loop {
8403 r#type = None;
8404 if self.buf.len() == self.pos {
8405 return None;
8406 }
8407 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8408 break;
8409 };
8410 r#type = Some(header.r#type);
8411 let res = match header.r#type {
8412 1u16 => OpPagePoolStatsGetDoReply::Info({
8413 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
8414 let Some(val) = res else { break };
8415 val
8416 }),
8417 8u16 => OpPagePoolStatsGetDoReply::AllocFast({
8418 let res = parse_u32(next);
8419 let Some(val) = res else { break };
8420 val
8421 }),
8422 9u16 => OpPagePoolStatsGetDoReply::AllocSlow({
8423 let res = parse_u32(next);
8424 let Some(val) = res else { break };
8425 val
8426 }),
8427 10u16 => OpPagePoolStatsGetDoReply::AllocSlowHighOrder({
8428 let res = parse_u32(next);
8429 let Some(val) = res else { break };
8430 val
8431 }),
8432 11u16 => OpPagePoolStatsGetDoReply::AllocEmpty({
8433 let res = parse_u32(next);
8434 let Some(val) = res else { break };
8435 val
8436 }),
8437 12u16 => OpPagePoolStatsGetDoReply::AllocRefill({
8438 let res = parse_u32(next);
8439 let Some(val) = res else { break };
8440 val
8441 }),
8442 13u16 => OpPagePoolStatsGetDoReply::AllocWaive({
8443 let res = parse_u32(next);
8444 let Some(val) = res else { break };
8445 val
8446 }),
8447 14u16 => OpPagePoolStatsGetDoReply::RecycleCached({
8448 let res = parse_u32(next);
8449 let Some(val) = res else { break };
8450 val
8451 }),
8452 15u16 => OpPagePoolStatsGetDoReply::RecycleCacheFull({
8453 let res = parse_u32(next);
8454 let Some(val) = res else { break };
8455 val
8456 }),
8457 16u16 => OpPagePoolStatsGetDoReply::RecycleRing({
8458 let res = parse_u32(next);
8459 let Some(val) = res else { break };
8460 val
8461 }),
8462 17u16 => OpPagePoolStatsGetDoReply::RecycleRingFull({
8463 let res = parse_u32(next);
8464 let Some(val) = res else { break };
8465 val
8466 }),
8467 18u16 => OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt({
8468 let res = parse_u32(next);
8469 let Some(val) = res else { break };
8470 val
8471 }),
8472 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8473 n => continue,
8474 };
8475 return Some(Ok(res));
8476 }
8477 Some(Err(ErrorContext::new(
8478 "OpPagePoolStatsGetDoReply",
8479 r#type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8480 self.orig_loc,
8481 self.buf.as_ptr().wrapping_add(pos) as usize,
8482 )))
8483 }
8484}
8485impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoReply<'_> {
8486 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8487 let mut fmt = f.debug_struct("OpPagePoolStatsGetDoReply");
8488 for attr in self.clone() {
8489 let attr = match attr {
8490 Ok(a) => a,
8491 Err(err) => {
8492 fmt.finish()?;
8493 f.write_str("Err(")?;
8494 err.fmt(f)?;
8495 return f.write_str(")");
8496 }
8497 };
8498 match attr {
8499 OpPagePoolStatsGetDoReply::Info(val) => fmt.field("Info", &val),
8500 OpPagePoolStatsGetDoReply::AllocFast(val) => fmt.field("AllocFast", &val),
8501 OpPagePoolStatsGetDoReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
8502 OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8503 fmt.field("AllocSlowHighOrder", &val)
8504 }
8505 OpPagePoolStatsGetDoReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
8506 OpPagePoolStatsGetDoReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
8507 OpPagePoolStatsGetDoReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
8508 OpPagePoolStatsGetDoReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
8509 OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8510 fmt.field("RecycleCacheFull", &val)
8511 }
8512 OpPagePoolStatsGetDoReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
8513 OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8514 fmt.field("RecycleRingFull", &val)
8515 }
8516 OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8517 fmt.field("RecycleReleasedRefcnt", &val)
8518 }
8519 };
8520 }
8521 fmt.finish()
8522 }
8523}
8524impl IterableOpPagePoolStatsGetDoReply<'_> {
8525 pub fn lookup_attr(
8526 &self,
8527 offset: usize,
8528 missing_type: Option<u16>,
8529 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8530 let mut stack = Vec::new();
8531 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8532 if cur == offset + PushBuiltinNfgenmsg::len() {
8533 stack.push(("OpPagePoolStatsGetDoReply", offset));
8534 return (
8535 stack,
8536 missing_type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8537 );
8538 }
8539 if cur > offset || cur + self.buf.len() < offset {
8540 return (stack, None);
8541 }
8542 let mut attrs = self.clone();
8543 let mut last_off = cur + attrs.pos;
8544 let mut missing = None;
8545 while let Some(attr) = attrs.next() {
8546 let Ok(attr) = attr else { break };
8547 match attr {
8548 OpPagePoolStatsGetDoReply::Info(val) => {
8549 (stack, missing) = val.lookup_attr(offset, missing_type);
8550 if !stack.is_empty() {
8551 break;
8552 }
8553 }
8554 OpPagePoolStatsGetDoReply::AllocFast(val) => {
8555 if last_off == offset {
8556 stack.push(("AllocFast", last_off));
8557 break;
8558 }
8559 }
8560 OpPagePoolStatsGetDoReply::AllocSlow(val) => {
8561 if last_off == offset {
8562 stack.push(("AllocSlow", last_off));
8563 break;
8564 }
8565 }
8566 OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8567 if last_off == offset {
8568 stack.push(("AllocSlowHighOrder", last_off));
8569 break;
8570 }
8571 }
8572 OpPagePoolStatsGetDoReply::AllocEmpty(val) => {
8573 if last_off == offset {
8574 stack.push(("AllocEmpty", last_off));
8575 break;
8576 }
8577 }
8578 OpPagePoolStatsGetDoReply::AllocRefill(val) => {
8579 if last_off == offset {
8580 stack.push(("AllocRefill", last_off));
8581 break;
8582 }
8583 }
8584 OpPagePoolStatsGetDoReply::AllocWaive(val) => {
8585 if last_off == offset {
8586 stack.push(("AllocWaive", last_off));
8587 break;
8588 }
8589 }
8590 OpPagePoolStatsGetDoReply::RecycleCached(val) => {
8591 if last_off == offset {
8592 stack.push(("RecycleCached", last_off));
8593 break;
8594 }
8595 }
8596 OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8597 if last_off == offset {
8598 stack.push(("RecycleCacheFull", last_off));
8599 break;
8600 }
8601 }
8602 OpPagePoolStatsGetDoReply::RecycleRing(val) => {
8603 if last_off == offset {
8604 stack.push(("RecycleRing", last_off));
8605 break;
8606 }
8607 }
8608 OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8609 if last_off == offset {
8610 stack.push(("RecycleRingFull", last_off));
8611 break;
8612 }
8613 }
8614 OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8615 if last_off == offset {
8616 stack.push(("RecycleReleasedRefcnt", last_off));
8617 break;
8618 }
8619 }
8620 _ => {}
8621 };
8622 last_off = cur + attrs.pos;
8623 }
8624 if !stack.is_empty() {
8625 stack.push(("OpPagePoolStatsGetDoReply", cur));
8626 }
8627 (stack, missing)
8628 }
8629}
8630#[derive(Debug)]
8631pub struct RequestOpPagePoolStatsGetDoRequest<'r> {
8632 request: Request<'r>,
8633}
8634impl<'r> RequestOpPagePoolStatsGetDoRequest<'r> {
8635 pub fn new(mut request: Request<'r>) -> Self {
8636 PushOpPagePoolStatsGetDoRequest::write_header(&mut request.buf_mut());
8637 Self { request: request }
8638 }
8639 pub fn encode(&mut self) -> PushOpPagePoolStatsGetDoRequest<&mut Vec<u8>> {
8640 PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf_mut())
8641 }
8642 pub fn into_encoder(self) -> PushOpPagePoolStatsGetDoRequest<RequestBuf<'r>> {
8643 PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf)
8644 }
8645 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpPagePoolStatsGetDoRequest<'buf> {
8646 OpPagePoolStatsGetDoRequest::new(buf)
8647 }
8648}
8649impl NetlinkRequest for RequestOpPagePoolStatsGetDoRequest<'_> {
8650 fn protocol(&self) -> Protocol {
8651 Protocol::Generic("netdev".as_bytes())
8652 }
8653 fn flags(&self) -> u16 {
8654 self.request.flags
8655 }
8656 fn payload(&self) -> &[u8] {
8657 self.request.buf()
8658 }
8659 type ReplyType<'buf> = IterableOpPagePoolStatsGetDoReply<'buf>;
8660 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8661 OpPagePoolStatsGetDoReply::new(buf)
8662 }
8663 fn lookup(
8664 buf: &[u8],
8665 offset: usize,
8666 missing_type: Option<u16>,
8667 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8668 OpPagePoolStatsGetDoRequest::new(buf).lookup_attr(offset, missing_type)
8669 }
8670}
8671#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8672pub struct PushOpQueueGetDumpRequest<Prev: Rec> {
8673 pub(crate) prev: Option<Prev>,
8674 pub(crate) header_offset: Option<usize>,
8675}
8676impl<Prev: Rec> Rec for PushOpQueueGetDumpRequest<Prev> {
8677 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8678 self.prev.as_mut().unwrap().as_rec_mut()
8679 }
8680 fn as_rec(&self) -> &Vec<u8> {
8681 self.prev.as_ref().unwrap().as_rec()
8682 }
8683}
8684impl<Prev: Rec> PushOpQueueGetDumpRequest<Prev> {
8685 pub fn new(mut prev: Prev) -> Self {
8686 Self::write_header(&mut prev);
8687 Self::new_without_header(prev)
8688 }
8689 fn new_without_header(prev: Prev) -> Self {
8690 Self {
8691 prev: Some(prev),
8692 header_offset: None,
8693 }
8694 }
8695 fn write_header(prev: &mut Prev) {
8696 let mut header = PushBuiltinNfgenmsg::new();
8697 header.set_cmd(10u8);
8698 header.set_version(1u8);
8699 prev.as_rec_mut().extend(header.as_slice());
8700 }
8701 pub fn end_nested(mut self) -> Prev {
8702 let mut prev = self.prev.take().unwrap();
8703 if let Some(header_offset) = &self.header_offset {
8704 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8705 }
8706 prev
8707 }
8708 #[doc = "ifindex of the netdevice to which the queue belongs."]
8709 pub fn push_ifindex(mut self, value: u32) -> Self {
8710 push_header(self.as_rec_mut(), 2u16, 4 as u16);
8711 self.as_rec_mut().extend(value.to_ne_bytes());
8712 self
8713 }
8714}
8715impl<Prev: Rec> Drop for PushOpQueueGetDumpRequest<Prev> {
8716 fn drop(&mut self) {
8717 if let Some(prev) = &mut self.prev {
8718 if let Some(header_offset) = &self.header_offset {
8719 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8720 }
8721 }
8722 }
8723}
8724#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8725#[derive(Clone)]
8726pub enum OpQueueGetDumpRequest {
8727 #[doc = "ifindex of the netdevice to which the queue belongs."]
8728 Ifindex(u32),
8729}
8730impl<'a> IterableOpQueueGetDumpRequest<'a> {
8731 #[doc = "ifindex of the netdevice to which the queue belongs."]
8732 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8733 let mut iter = self.clone();
8734 iter.pos = 0;
8735 for attr in iter {
8736 if let OpQueueGetDumpRequest::Ifindex(val) = attr? {
8737 return Ok(val);
8738 }
8739 }
8740 Err(ErrorContext::new_missing(
8741 "OpQueueGetDumpRequest",
8742 "Ifindex",
8743 self.orig_loc,
8744 self.buf.as_ptr() as usize,
8745 ))
8746 }
8747}
8748impl OpQueueGetDumpRequest {
8749 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpRequest<'a> {
8750 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8751 IterableOpQueueGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
8752 }
8753 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8754 Queue::attr_from_type(r#type)
8755 }
8756}
8757#[derive(Clone, Copy, Default)]
8758pub struct IterableOpQueueGetDumpRequest<'a> {
8759 buf: &'a [u8],
8760 pos: usize,
8761 orig_loc: usize,
8762}
8763impl<'a> IterableOpQueueGetDumpRequest<'a> {
8764 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8765 Self {
8766 buf,
8767 pos: 0,
8768 orig_loc,
8769 }
8770 }
8771 pub fn get_buf(&self) -> &'a [u8] {
8772 self.buf
8773 }
8774}
8775impl<'a> Iterator for IterableOpQueueGetDumpRequest<'a> {
8776 type Item = Result<OpQueueGetDumpRequest, ErrorContext>;
8777 fn next(&mut self) -> Option<Self::Item> {
8778 let pos = self.pos;
8779 let mut r#type;
8780 loop {
8781 r#type = None;
8782 if self.buf.len() == self.pos {
8783 return None;
8784 }
8785 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
8786 break;
8787 };
8788 r#type = Some(header.r#type);
8789 let res = match header.r#type {
8790 2u16 => OpQueueGetDumpRequest::Ifindex({
8791 let res = parse_u32(next);
8792 let Some(val) = res else { break };
8793 val
8794 }),
8795 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
8796 n => continue,
8797 };
8798 return Some(Ok(res));
8799 }
8800 Some(Err(ErrorContext::new(
8801 "OpQueueGetDumpRequest",
8802 r#type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8803 self.orig_loc,
8804 self.buf.as_ptr().wrapping_add(pos) as usize,
8805 )))
8806 }
8807}
8808impl std::fmt::Debug for IterableOpQueueGetDumpRequest<'_> {
8809 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8810 let mut fmt = f.debug_struct("OpQueueGetDumpRequest");
8811 for attr in self.clone() {
8812 let attr = match attr {
8813 Ok(a) => a,
8814 Err(err) => {
8815 fmt.finish()?;
8816 f.write_str("Err(")?;
8817 err.fmt(f)?;
8818 return f.write_str(")");
8819 }
8820 };
8821 match attr {
8822 OpQueueGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
8823 };
8824 }
8825 fmt.finish()
8826 }
8827}
8828impl IterableOpQueueGetDumpRequest<'_> {
8829 pub fn lookup_attr(
8830 &self,
8831 offset: usize,
8832 missing_type: Option<u16>,
8833 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8834 let mut stack = Vec::new();
8835 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8836 if cur == offset + PushBuiltinNfgenmsg::len() {
8837 stack.push(("OpQueueGetDumpRequest", offset));
8838 return (
8839 stack,
8840 missing_type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8841 );
8842 }
8843 if cur > offset || cur + self.buf.len() < offset {
8844 return (stack, None);
8845 }
8846 let mut attrs = self.clone();
8847 let mut last_off = cur + attrs.pos;
8848 while let Some(attr) = attrs.next() {
8849 let Ok(attr) = attr else { break };
8850 match attr {
8851 OpQueueGetDumpRequest::Ifindex(val) => {
8852 if last_off == offset {
8853 stack.push(("Ifindex", last_off));
8854 break;
8855 }
8856 }
8857 _ => {}
8858 };
8859 last_off = cur + attrs.pos;
8860 }
8861 if !stack.is_empty() {
8862 stack.push(("OpQueueGetDumpRequest", cur));
8863 }
8864 (stack, None)
8865 }
8866}
8867#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8868pub struct PushOpQueueGetDumpReply<Prev: Rec> {
8869 pub(crate) prev: Option<Prev>,
8870 pub(crate) header_offset: Option<usize>,
8871}
8872impl<Prev: Rec> Rec for PushOpQueueGetDumpReply<Prev> {
8873 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8874 self.prev.as_mut().unwrap().as_rec_mut()
8875 }
8876 fn as_rec(&self) -> &Vec<u8> {
8877 self.prev.as_ref().unwrap().as_rec()
8878 }
8879}
8880impl<Prev: Rec> PushOpQueueGetDumpReply<Prev> {
8881 pub fn new(mut prev: Prev) -> Self {
8882 Self::write_header(&mut prev);
8883 Self::new_without_header(prev)
8884 }
8885 fn new_without_header(prev: Prev) -> Self {
8886 Self {
8887 prev: Some(prev),
8888 header_offset: None,
8889 }
8890 }
8891 fn write_header(prev: &mut Prev) {
8892 let mut header = PushBuiltinNfgenmsg::new();
8893 header.set_cmd(10u8);
8894 header.set_version(1u8);
8895 prev.as_rec_mut().extend(header.as_slice());
8896 }
8897 pub fn end_nested(mut self) -> Prev {
8898 let mut prev = self.prev.take().unwrap();
8899 if let Some(header_offset) = &self.header_offset {
8900 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8901 }
8902 prev
8903 }
8904 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8905 pub fn push_id(mut self, value: u32) -> Self {
8906 push_header(self.as_rec_mut(), 1u16, 4 as u16);
8907 self.as_rec_mut().extend(value.to_ne_bytes());
8908 self
8909 }
8910 #[doc = "ifindex of the netdevice to which the queue belongs."]
8911 pub fn push_ifindex(mut self, value: u32) -> Self {
8912 push_header(self.as_rec_mut(), 2u16, 4 as u16);
8913 self.as_rec_mut().extend(value.to_ne_bytes());
8914 self
8915 }
8916 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
8917 pub fn push_type(mut self, value: u32) -> Self {
8918 push_header(self.as_rec_mut(), 3u16, 4 as u16);
8919 self.as_rec_mut().extend(value.to_ne_bytes());
8920 self
8921 }
8922 #[doc = "ID of the NAPI instance which services this queue."]
8923 pub fn push_napi_id(mut self, value: u32) -> Self {
8924 push_header(self.as_rec_mut(), 4u16, 4 as u16);
8925 self.as_rec_mut().extend(value.to_ne_bytes());
8926 self
8927 }
8928 #[doc = "ID of the dmabuf attached to this queue, if any."]
8929 pub fn push_dmabuf(mut self, value: u32) -> Self {
8930 push_header(self.as_rec_mut(), 5u16, 4 as u16);
8931 self.as_rec_mut().extend(value.to_ne_bytes());
8932 self
8933 }
8934 #[doc = "io_uring memory provider information."]
8935 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
8936 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
8937 PushIoUringProviderInfo {
8938 prev: Some(self),
8939 header_offset: Some(header_offset),
8940 }
8941 }
8942 #[doc = "XSK information for this queue, if any."]
8943 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
8944 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
8945 PushXskInfo {
8946 prev: Some(self),
8947 header_offset: Some(header_offset),
8948 }
8949 }
8950}
8951impl<Prev: Rec> Drop for PushOpQueueGetDumpReply<Prev> {
8952 fn drop(&mut self) {
8953 if let Some(prev) = &mut self.prev {
8954 if let Some(header_offset) = &self.header_offset {
8955 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8956 }
8957 }
8958 }
8959}
8960#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8961#[derive(Clone)]
8962pub enum OpQueueGetDumpReply<'a> {
8963 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8964 Id(u32),
8965 #[doc = "ifindex of the netdevice to which the queue belongs."]
8966 Ifindex(u32),
8967 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
8968 Type(u32),
8969 #[doc = "ID of the NAPI instance which services this queue."]
8970 NapiId(u32),
8971 #[doc = "ID of the dmabuf attached to this queue, if any."]
8972 Dmabuf(u32),
8973 #[doc = "io_uring memory provider information."]
8974 IoUring(IterableIoUringProviderInfo<'a>),
8975 #[doc = "XSK information for this queue, if any."]
8976 Xsk(IterableXskInfo<'a>),
8977}
8978impl<'a> IterableOpQueueGetDumpReply<'a> {
8979 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
8980 pub fn get_id(&self) -> Result<u32, ErrorContext> {
8981 let mut iter = self.clone();
8982 iter.pos = 0;
8983 for attr in iter {
8984 if let OpQueueGetDumpReply::Id(val) = attr? {
8985 return Ok(val);
8986 }
8987 }
8988 Err(ErrorContext::new_missing(
8989 "OpQueueGetDumpReply",
8990 "Id",
8991 self.orig_loc,
8992 self.buf.as_ptr() as usize,
8993 ))
8994 }
8995 #[doc = "ifindex of the netdevice to which the queue belongs."]
8996 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8997 let mut iter = self.clone();
8998 iter.pos = 0;
8999 for attr in iter {
9000 if let OpQueueGetDumpReply::Ifindex(val) = attr? {
9001 return Ok(val);
9002 }
9003 }
9004 Err(ErrorContext::new_missing(
9005 "OpQueueGetDumpReply",
9006 "Ifindex",
9007 self.orig_loc,
9008 self.buf.as_ptr() as usize,
9009 ))
9010 }
9011 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9012 pub fn get_type(&self) -> Result<u32, ErrorContext> {
9013 let mut iter = self.clone();
9014 iter.pos = 0;
9015 for attr in iter {
9016 if let OpQueueGetDumpReply::Type(val) = attr? {
9017 return Ok(val);
9018 }
9019 }
9020 Err(ErrorContext::new_missing(
9021 "OpQueueGetDumpReply",
9022 "Type",
9023 self.orig_loc,
9024 self.buf.as_ptr() as usize,
9025 ))
9026 }
9027 #[doc = "ID of the NAPI instance which services this queue."]
9028 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9029 let mut iter = self.clone();
9030 iter.pos = 0;
9031 for attr in iter {
9032 if let OpQueueGetDumpReply::NapiId(val) = attr? {
9033 return Ok(val);
9034 }
9035 }
9036 Err(ErrorContext::new_missing(
9037 "OpQueueGetDumpReply",
9038 "NapiId",
9039 self.orig_loc,
9040 self.buf.as_ptr() as usize,
9041 ))
9042 }
9043 #[doc = "ID of the dmabuf attached to this queue, if any."]
9044 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9045 let mut iter = self.clone();
9046 iter.pos = 0;
9047 for attr in iter {
9048 if let OpQueueGetDumpReply::Dmabuf(val) = attr? {
9049 return Ok(val);
9050 }
9051 }
9052 Err(ErrorContext::new_missing(
9053 "OpQueueGetDumpReply",
9054 "Dmabuf",
9055 self.orig_loc,
9056 self.buf.as_ptr() as usize,
9057 ))
9058 }
9059 #[doc = "io_uring memory provider information."]
9060 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9061 let mut iter = self.clone();
9062 iter.pos = 0;
9063 for attr in iter {
9064 if let OpQueueGetDumpReply::IoUring(val) = attr? {
9065 return Ok(val);
9066 }
9067 }
9068 Err(ErrorContext::new_missing(
9069 "OpQueueGetDumpReply",
9070 "IoUring",
9071 self.orig_loc,
9072 self.buf.as_ptr() as usize,
9073 ))
9074 }
9075 #[doc = "XSK information for this queue, if any."]
9076 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9077 let mut iter = self.clone();
9078 iter.pos = 0;
9079 for attr in iter {
9080 if let OpQueueGetDumpReply::Xsk(val) = attr? {
9081 return Ok(val);
9082 }
9083 }
9084 Err(ErrorContext::new_missing(
9085 "OpQueueGetDumpReply",
9086 "Xsk",
9087 self.orig_loc,
9088 self.buf.as_ptr() as usize,
9089 ))
9090 }
9091}
9092impl OpQueueGetDumpReply<'_> {
9093 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpReply<'a> {
9094 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9095 IterableOpQueueGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
9096 }
9097 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9098 Queue::attr_from_type(r#type)
9099 }
9100}
9101#[derive(Clone, Copy, Default)]
9102pub struct IterableOpQueueGetDumpReply<'a> {
9103 buf: &'a [u8],
9104 pos: usize,
9105 orig_loc: usize,
9106}
9107impl<'a> IterableOpQueueGetDumpReply<'a> {
9108 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9109 Self {
9110 buf,
9111 pos: 0,
9112 orig_loc,
9113 }
9114 }
9115 pub fn get_buf(&self) -> &'a [u8] {
9116 self.buf
9117 }
9118}
9119impl<'a> Iterator for IterableOpQueueGetDumpReply<'a> {
9120 type Item = Result<OpQueueGetDumpReply<'a>, ErrorContext>;
9121 fn next(&mut self) -> Option<Self::Item> {
9122 let pos = self.pos;
9123 let mut r#type;
9124 loop {
9125 r#type = None;
9126 if self.buf.len() == self.pos {
9127 return None;
9128 }
9129 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9130 break;
9131 };
9132 r#type = Some(header.r#type);
9133 let res = match header.r#type {
9134 1u16 => OpQueueGetDumpReply::Id({
9135 let res = parse_u32(next);
9136 let Some(val) = res else { break };
9137 val
9138 }),
9139 2u16 => OpQueueGetDumpReply::Ifindex({
9140 let res = parse_u32(next);
9141 let Some(val) = res else { break };
9142 val
9143 }),
9144 3u16 => OpQueueGetDumpReply::Type({
9145 let res = parse_u32(next);
9146 let Some(val) = res else { break };
9147 val
9148 }),
9149 4u16 => OpQueueGetDumpReply::NapiId({
9150 let res = parse_u32(next);
9151 let Some(val) = res else { break };
9152 val
9153 }),
9154 5u16 => OpQueueGetDumpReply::Dmabuf({
9155 let res = parse_u32(next);
9156 let Some(val) = res else { break };
9157 val
9158 }),
9159 6u16 => OpQueueGetDumpReply::IoUring({
9160 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9161 let Some(val) = res else { break };
9162 val
9163 }),
9164 7u16 => OpQueueGetDumpReply::Xsk({
9165 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9166 let Some(val) = res else { break };
9167 val
9168 }),
9169 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9170 n => continue,
9171 };
9172 return Some(Ok(res));
9173 }
9174 Some(Err(ErrorContext::new(
9175 "OpQueueGetDumpReply",
9176 r#type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9177 self.orig_loc,
9178 self.buf.as_ptr().wrapping_add(pos) as usize,
9179 )))
9180 }
9181}
9182impl<'a> std::fmt::Debug for IterableOpQueueGetDumpReply<'_> {
9183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9184 let mut fmt = f.debug_struct("OpQueueGetDumpReply");
9185 for attr in self.clone() {
9186 let attr = match attr {
9187 Ok(a) => a,
9188 Err(err) => {
9189 fmt.finish()?;
9190 f.write_str("Err(")?;
9191 err.fmt(f)?;
9192 return f.write_str(")");
9193 }
9194 };
9195 match attr {
9196 OpQueueGetDumpReply::Id(val) => fmt.field("Id", &val),
9197 OpQueueGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
9198 OpQueueGetDumpReply::Type(val) => {
9199 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9200 }
9201 OpQueueGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
9202 OpQueueGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9203 OpQueueGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
9204 OpQueueGetDumpReply::Xsk(val) => fmt.field("Xsk", &val),
9205 };
9206 }
9207 fmt.finish()
9208 }
9209}
9210impl IterableOpQueueGetDumpReply<'_> {
9211 pub fn lookup_attr(
9212 &self,
9213 offset: usize,
9214 missing_type: Option<u16>,
9215 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9216 let mut stack = Vec::new();
9217 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9218 if cur == offset + PushBuiltinNfgenmsg::len() {
9219 stack.push(("OpQueueGetDumpReply", offset));
9220 return (
9221 stack,
9222 missing_type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9223 );
9224 }
9225 if cur > offset || cur + self.buf.len() < offset {
9226 return (stack, None);
9227 }
9228 let mut attrs = self.clone();
9229 let mut last_off = cur + attrs.pos;
9230 let mut missing = None;
9231 while let Some(attr) = attrs.next() {
9232 let Ok(attr) = attr else { break };
9233 match attr {
9234 OpQueueGetDumpReply::Id(val) => {
9235 if last_off == offset {
9236 stack.push(("Id", last_off));
9237 break;
9238 }
9239 }
9240 OpQueueGetDumpReply::Ifindex(val) => {
9241 if last_off == offset {
9242 stack.push(("Ifindex", last_off));
9243 break;
9244 }
9245 }
9246 OpQueueGetDumpReply::Type(val) => {
9247 if last_off == offset {
9248 stack.push(("Type", last_off));
9249 break;
9250 }
9251 }
9252 OpQueueGetDumpReply::NapiId(val) => {
9253 if last_off == offset {
9254 stack.push(("NapiId", last_off));
9255 break;
9256 }
9257 }
9258 OpQueueGetDumpReply::Dmabuf(val) => {
9259 if last_off == offset {
9260 stack.push(("Dmabuf", last_off));
9261 break;
9262 }
9263 }
9264 OpQueueGetDumpReply::IoUring(val) => {
9265 (stack, missing) = val.lookup_attr(offset, missing_type);
9266 if !stack.is_empty() {
9267 break;
9268 }
9269 }
9270 OpQueueGetDumpReply::Xsk(val) => {
9271 (stack, missing) = val.lookup_attr(offset, missing_type);
9272 if !stack.is_empty() {
9273 break;
9274 }
9275 }
9276 _ => {}
9277 };
9278 last_off = cur + attrs.pos;
9279 }
9280 if !stack.is_empty() {
9281 stack.push(("OpQueueGetDumpReply", cur));
9282 }
9283 (stack, missing)
9284 }
9285}
9286#[derive(Debug)]
9287pub struct RequestOpQueueGetDumpRequest<'r> {
9288 request: Request<'r>,
9289}
9290impl<'r> RequestOpQueueGetDumpRequest<'r> {
9291 pub fn new(mut request: Request<'r>) -> Self {
9292 PushOpQueueGetDumpRequest::write_header(&mut request.buf_mut());
9293 Self {
9294 request: request.set_dump(),
9295 }
9296 }
9297 pub fn encode(&mut self) -> PushOpQueueGetDumpRequest<&mut Vec<u8>> {
9298 PushOpQueueGetDumpRequest::new_without_header(self.request.buf_mut())
9299 }
9300 pub fn into_encoder(self) -> PushOpQueueGetDumpRequest<RequestBuf<'r>> {
9301 PushOpQueueGetDumpRequest::new_without_header(self.request.buf)
9302 }
9303 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQueueGetDumpRequest<'buf> {
9304 OpQueueGetDumpRequest::new(buf)
9305 }
9306}
9307impl NetlinkRequest for RequestOpQueueGetDumpRequest<'_> {
9308 fn protocol(&self) -> Protocol {
9309 Protocol::Generic("netdev".as_bytes())
9310 }
9311 fn flags(&self) -> u16 {
9312 self.request.flags
9313 }
9314 fn payload(&self) -> &[u8] {
9315 self.request.buf()
9316 }
9317 type ReplyType<'buf> = IterableOpQueueGetDumpReply<'buf>;
9318 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9319 OpQueueGetDumpReply::new(buf)
9320 }
9321 fn lookup(
9322 buf: &[u8],
9323 offset: usize,
9324 missing_type: Option<u16>,
9325 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9326 OpQueueGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
9327 }
9328}
9329#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9330pub struct PushOpQueueGetDoRequest<Prev: Rec> {
9331 pub(crate) prev: Option<Prev>,
9332 pub(crate) header_offset: Option<usize>,
9333}
9334impl<Prev: Rec> Rec for PushOpQueueGetDoRequest<Prev> {
9335 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9336 self.prev.as_mut().unwrap().as_rec_mut()
9337 }
9338 fn as_rec(&self) -> &Vec<u8> {
9339 self.prev.as_ref().unwrap().as_rec()
9340 }
9341}
9342impl<Prev: Rec> PushOpQueueGetDoRequest<Prev> {
9343 pub fn new(mut prev: Prev) -> Self {
9344 Self::write_header(&mut prev);
9345 Self::new_without_header(prev)
9346 }
9347 fn new_without_header(prev: Prev) -> Self {
9348 Self {
9349 prev: Some(prev),
9350 header_offset: None,
9351 }
9352 }
9353 fn write_header(prev: &mut Prev) {
9354 let mut header = PushBuiltinNfgenmsg::new();
9355 header.set_cmd(10u8);
9356 header.set_version(1u8);
9357 prev.as_rec_mut().extend(header.as_slice());
9358 }
9359 pub fn end_nested(mut self) -> Prev {
9360 let mut prev = self.prev.take().unwrap();
9361 if let Some(header_offset) = &self.header_offset {
9362 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9363 }
9364 prev
9365 }
9366 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9367 pub fn push_id(mut self, value: u32) -> Self {
9368 push_header(self.as_rec_mut(), 1u16, 4 as u16);
9369 self.as_rec_mut().extend(value.to_ne_bytes());
9370 self
9371 }
9372 #[doc = "ifindex of the netdevice to which the queue belongs."]
9373 pub fn push_ifindex(mut self, value: u32) -> Self {
9374 push_header(self.as_rec_mut(), 2u16, 4 as u16);
9375 self.as_rec_mut().extend(value.to_ne_bytes());
9376 self
9377 }
9378 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9379 pub fn push_type(mut self, value: u32) -> Self {
9380 push_header(self.as_rec_mut(), 3u16, 4 as u16);
9381 self.as_rec_mut().extend(value.to_ne_bytes());
9382 self
9383 }
9384}
9385impl<Prev: Rec> Drop for PushOpQueueGetDoRequest<Prev> {
9386 fn drop(&mut self) {
9387 if let Some(prev) = &mut self.prev {
9388 if let Some(header_offset) = &self.header_offset {
9389 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9390 }
9391 }
9392 }
9393}
9394#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9395#[derive(Clone)]
9396pub enum OpQueueGetDoRequest {
9397 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9398 Id(u32),
9399 #[doc = "ifindex of the netdevice to which the queue belongs."]
9400 Ifindex(u32),
9401 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9402 Type(u32),
9403}
9404impl<'a> IterableOpQueueGetDoRequest<'a> {
9405 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9406 pub fn get_id(&self) -> Result<u32, ErrorContext> {
9407 let mut iter = self.clone();
9408 iter.pos = 0;
9409 for attr in iter {
9410 if let OpQueueGetDoRequest::Id(val) = attr? {
9411 return Ok(val);
9412 }
9413 }
9414 Err(ErrorContext::new_missing(
9415 "OpQueueGetDoRequest",
9416 "Id",
9417 self.orig_loc,
9418 self.buf.as_ptr() as usize,
9419 ))
9420 }
9421 #[doc = "ifindex of the netdevice to which the queue belongs."]
9422 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9423 let mut iter = self.clone();
9424 iter.pos = 0;
9425 for attr in iter {
9426 if let OpQueueGetDoRequest::Ifindex(val) = attr? {
9427 return Ok(val);
9428 }
9429 }
9430 Err(ErrorContext::new_missing(
9431 "OpQueueGetDoRequest",
9432 "Ifindex",
9433 self.orig_loc,
9434 self.buf.as_ptr() as usize,
9435 ))
9436 }
9437 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9438 pub fn get_type(&self) -> Result<u32, ErrorContext> {
9439 let mut iter = self.clone();
9440 iter.pos = 0;
9441 for attr in iter {
9442 if let OpQueueGetDoRequest::Type(val) = attr? {
9443 return Ok(val);
9444 }
9445 }
9446 Err(ErrorContext::new_missing(
9447 "OpQueueGetDoRequest",
9448 "Type",
9449 self.orig_loc,
9450 self.buf.as_ptr() as usize,
9451 ))
9452 }
9453}
9454impl OpQueueGetDoRequest {
9455 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoRequest<'a> {
9456 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9457 IterableOpQueueGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
9458 }
9459 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9460 Queue::attr_from_type(r#type)
9461 }
9462}
9463#[derive(Clone, Copy, Default)]
9464pub struct IterableOpQueueGetDoRequest<'a> {
9465 buf: &'a [u8],
9466 pos: usize,
9467 orig_loc: usize,
9468}
9469impl<'a> IterableOpQueueGetDoRequest<'a> {
9470 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9471 Self {
9472 buf,
9473 pos: 0,
9474 orig_loc,
9475 }
9476 }
9477 pub fn get_buf(&self) -> &'a [u8] {
9478 self.buf
9479 }
9480}
9481impl<'a> Iterator for IterableOpQueueGetDoRequest<'a> {
9482 type Item = Result<OpQueueGetDoRequest, ErrorContext>;
9483 fn next(&mut self) -> Option<Self::Item> {
9484 let pos = self.pos;
9485 let mut r#type;
9486 loop {
9487 r#type = None;
9488 if self.buf.len() == self.pos {
9489 return None;
9490 }
9491 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9492 break;
9493 };
9494 r#type = Some(header.r#type);
9495 let res = match header.r#type {
9496 1u16 => OpQueueGetDoRequest::Id({
9497 let res = parse_u32(next);
9498 let Some(val) = res else { break };
9499 val
9500 }),
9501 2u16 => OpQueueGetDoRequest::Ifindex({
9502 let res = parse_u32(next);
9503 let Some(val) = res else { break };
9504 val
9505 }),
9506 3u16 => OpQueueGetDoRequest::Type({
9507 let res = parse_u32(next);
9508 let Some(val) = res else { break };
9509 val
9510 }),
9511 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9512 n => continue,
9513 };
9514 return Some(Ok(res));
9515 }
9516 Some(Err(ErrorContext::new(
9517 "OpQueueGetDoRequest",
9518 r#type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9519 self.orig_loc,
9520 self.buf.as_ptr().wrapping_add(pos) as usize,
9521 )))
9522 }
9523}
9524impl std::fmt::Debug for IterableOpQueueGetDoRequest<'_> {
9525 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9526 let mut fmt = f.debug_struct("OpQueueGetDoRequest");
9527 for attr in self.clone() {
9528 let attr = match attr {
9529 Ok(a) => a,
9530 Err(err) => {
9531 fmt.finish()?;
9532 f.write_str("Err(")?;
9533 err.fmt(f)?;
9534 return f.write_str(")");
9535 }
9536 };
9537 match attr {
9538 OpQueueGetDoRequest::Id(val) => fmt.field("Id", &val),
9539 OpQueueGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
9540 OpQueueGetDoRequest::Type(val) => {
9541 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9542 }
9543 };
9544 }
9545 fmt.finish()
9546 }
9547}
9548impl IterableOpQueueGetDoRequest<'_> {
9549 pub fn lookup_attr(
9550 &self,
9551 offset: usize,
9552 missing_type: Option<u16>,
9553 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9554 let mut stack = Vec::new();
9555 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9556 if cur == offset + PushBuiltinNfgenmsg::len() {
9557 stack.push(("OpQueueGetDoRequest", offset));
9558 return (
9559 stack,
9560 missing_type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9561 );
9562 }
9563 if cur > offset || cur + self.buf.len() < offset {
9564 return (stack, None);
9565 }
9566 let mut attrs = self.clone();
9567 let mut last_off = cur + attrs.pos;
9568 while let Some(attr) = attrs.next() {
9569 let Ok(attr) = attr else { break };
9570 match attr {
9571 OpQueueGetDoRequest::Id(val) => {
9572 if last_off == offset {
9573 stack.push(("Id", last_off));
9574 break;
9575 }
9576 }
9577 OpQueueGetDoRequest::Ifindex(val) => {
9578 if last_off == offset {
9579 stack.push(("Ifindex", last_off));
9580 break;
9581 }
9582 }
9583 OpQueueGetDoRequest::Type(val) => {
9584 if last_off == offset {
9585 stack.push(("Type", last_off));
9586 break;
9587 }
9588 }
9589 _ => {}
9590 };
9591 last_off = cur + attrs.pos;
9592 }
9593 if !stack.is_empty() {
9594 stack.push(("OpQueueGetDoRequest", cur));
9595 }
9596 (stack, None)
9597 }
9598}
9599#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9600pub struct PushOpQueueGetDoReply<Prev: Rec> {
9601 pub(crate) prev: Option<Prev>,
9602 pub(crate) header_offset: Option<usize>,
9603}
9604impl<Prev: Rec> Rec for PushOpQueueGetDoReply<Prev> {
9605 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9606 self.prev.as_mut().unwrap().as_rec_mut()
9607 }
9608 fn as_rec(&self) -> &Vec<u8> {
9609 self.prev.as_ref().unwrap().as_rec()
9610 }
9611}
9612impl<Prev: Rec> PushOpQueueGetDoReply<Prev> {
9613 pub fn new(mut prev: Prev) -> Self {
9614 Self::write_header(&mut prev);
9615 Self::new_without_header(prev)
9616 }
9617 fn new_without_header(prev: Prev) -> Self {
9618 Self {
9619 prev: Some(prev),
9620 header_offset: None,
9621 }
9622 }
9623 fn write_header(prev: &mut Prev) {
9624 let mut header = PushBuiltinNfgenmsg::new();
9625 header.set_cmd(10u8);
9626 header.set_version(1u8);
9627 prev.as_rec_mut().extend(header.as_slice());
9628 }
9629 pub fn end_nested(mut self) -> Prev {
9630 let mut prev = self.prev.take().unwrap();
9631 if let Some(header_offset) = &self.header_offset {
9632 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9633 }
9634 prev
9635 }
9636 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9637 pub fn push_id(mut self, value: u32) -> Self {
9638 push_header(self.as_rec_mut(), 1u16, 4 as u16);
9639 self.as_rec_mut().extend(value.to_ne_bytes());
9640 self
9641 }
9642 #[doc = "ifindex of the netdevice to which the queue belongs."]
9643 pub fn push_ifindex(mut self, value: u32) -> Self {
9644 push_header(self.as_rec_mut(), 2u16, 4 as u16);
9645 self.as_rec_mut().extend(value.to_ne_bytes());
9646 self
9647 }
9648 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9649 pub fn push_type(mut self, value: u32) -> Self {
9650 push_header(self.as_rec_mut(), 3u16, 4 as u16);
9651 self.as_rec_mut().extend(value.to_ne_bytes());
9652 self
9653 }
9654 #[doc = "ID of the NAPI instance which services this queue."]
9655 pub fn push_napi_id(mut self, value: u32) -> Self {
9656 push_header(self.as_rec_mut(), 4u16, 4 as u16);
9657 self.as_rec_mut().extend(value.to_ne_bytes());
9658 self
9659 }
9660 #[doc = "ID of the dmabuf attached to this queue, if any."]
9661 pub fn push_dmabuf(mut self, value: u32) -> Self {
9662 push_header(self.as_rec_mut(), 5u16, 4 as u16);
9663 self.as_rec_mut().extend(value.to_ne_bytes());
9664 self
9665 }
9666 #[doc = "io_uring memory provider information."]
9667 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
9668 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
9669 PushIoUringProviderInfo {
9670 prev: Some(self),
9671 header_offset: Some(header_offset),
9672 }
9673 }
9674 #[doc = "XSK information for this queue, if any."]
9675 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
9676 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
9677 PushXskInfo {
9678 prev: Some(self),
9679 header_offset: Some(header_offset),
9680 }
9681 }
9682}
9683impl<Prev: Rec> Drop for PushOpQueueGetDoReply<Prev> {
9684 fn drop(&mut self) {
9685 if let Some(prev) = &mut self.prev {
9686 if let Some(header_offset) = &self.header_offset {
9687 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9688 }
9689 }
9690 }
9691}
9692#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9693#[derive(Clone)]
9694pub enum OpQueueGetDoReply<'a> {
9695 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9696 Id(u32),
9697 #[doc = "ifindex of the netdevice to which the queue belongs."]
9698 Ifindex(u32),
9699 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9700 Type(u32),
9701 #[doc = "ID of the NAPI instance which services this queue."]
9702 NapiId(u32),
9703 #[doc = "ID of the dmabuf attached to this queue, if any."]
9704 Dmabuf(u32),
9705 #[doc = "io_uring memory provider information."]
9706 IoUring(IterableIoUringProviderInfo<'a>),
9707 #[doc = "XSK information for this queue, if any."]
9708 Xsk(IterableXskInfo<'a>),
9709}
9710impl<'a> IterableOpQueueGetDoReply<'a> {
9711 #[doc = "Queue index; most queue types are indexed like a C array, with indexes starting at 0 and ending at queue count - 1. Queue indexes are scoped to an interface and queue type."]
9712 pub fn get_id(&self) -> Result<u32, ErrorContext> {
9713 let mut iter = self.clone();
9714 iter.pos = 0;
9715 for attr in iter {
9716 if let OpQueueGetDoReply::Id(val) = attr? {
9717 return Ok(val);
9718 }
9719 }
9720 Err(ErrorContext::new_missing(
9721 "OpQueueGetDoReply",
9722 "Id",
9723 self.orig_loc,
9724 self.buf.as_ptr() as usize,
9725 ))
9726 }
9727 #[doc = "ifindex of the netdevice to which the queue belongs."]
9728 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9729 let mut iter = self.clone();
9730 iter.pos = 0;
9731 for attr in iter {
9732 if let OpQueueGetDoReply::Ifindex(val) = attr? {
9733 return Ok(val);
9734 }
9735 }
9736 Err(ErrorContext::new_missing(
9737 "OpQueueGetDoReply",
9738 "Ifindex",
9739 self.orig_loc,
9740 self.buf.as_ptr() as usize,
9741 ))
9742 }
9743 #[doc = "Queue type as rx, tx. Each queue type defines a separate ID space. XDP TX queues allocated in the kernel are not linked to NAPIs and thus not listed. AF_XDP queues will have more information set in the xsk attribute.\nAssociated type: \"QueueType\" (enum)"]
9744 pub fn get_type(&self) -> Result<u32, ErrorContext> {
9745 let mut iter = self.clone();
9746 iter.pos = 0;
9747 for attr in iter {
9748 if let OpQueueGetDoReply::Type(val) = attr? {
9749 return Ok(val);
9750 }
9751 }
9752 Err(ErrorContext::new_missing(
9753 "OpQueueGetDoReply",
9754 "Type",
9755 self.orig_loc,
9756 self.buf.as_ptr() as usize,
9757 ))
9758 }
9759 #[doc = "ID of the NAPI instance which services this queue."]
9760 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9761 let mut iter = self.clone();
9762 iter.pos = 0;
9763 for attr in iter {
9764 if let OpQueueGetDoReply::NapiId(val) = attr? {
9765 return Ok(val);
9766 }
9767 }
9768 Err(ErrorContext::new_missing(
9769 "OpQueueGetDoReply",
9770 "NapiId",
9771 self.orig_loc,
9772 self.buf.as_ptr() as usize,
9773 ))
9774 }
9775 #[doc = "ID of the dmabuf attached to this queue, if any."]
9776 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9777 let mut iter = self.clone();
9778 iter.pos = 0;
9779 for attr in iter {
9780 if let OpQueueGetDoReply::Dmabuf(val) = attr? {
9781 return Ok(val);
9782 }
9783 }
9784 Err(ErrorContext::new_missing(
9785 "OpQueueGetDoReply",
9786 "Dmabuf",
9787 self.orig_loc,
9788 self.buf.as_ptr() as usize,
9789 ))
9790 }
9791 #[doc = "io_uring memory provider information."]
9792 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9793 let mut iter = self.clone();
9794 iter.pos = 0;
9795 for attr in iter {
9796 if let OpQueueGetDoReply::IoUring(val) = attr? {
9797 return Ok(val);
9798 }
9799 }
9800 Err(ErrorContext::new_missing(
9801 "OpQueueGetDoReply",
9802 "IoUring",
9803 self.orig_loc,
9804 self.buf.as_ptr() as usize,
9805 ))
9806 }
9807 #[doc = "XSK information for this queue, if any."]
9808 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9809 let mut iter = self.clone();
9810 iter.pos = 0;
9811 for attr in iter {
9812 if let OpQueueGetDoReply::Xsk(val) = attr? {
9813 return Ok(val);
9814 }
9815 }
9816 Err(ErrorContext::new_missing(
9817 "OpQueueGetDoReply",
9818 "Xsk",
9819 self.orig_loc,
9820 self.buf.as_ptr() as usize,
9821 ))
9822 }
9823}
9824impl OpQueueGetDoReply<'_> {
9825 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoReply<'a> {
9826 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9827 IterableOpQueueGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
9828 }
9829 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9830 Queue::attr_from_type(r#type)
9831 }
9832}
9833#[derive(Clone, Copy, Default)]
9834pub struct IterableOpQueueGetDoReply<'a> {
9835 buf: &'a [u8],
9836 pos: usize,
9837 orig_loc: usize,
9838}
9839impl<'a> IterableOpQueueGetDoReply<'a> {
9840 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9841 Self {
9842 buf,
9843 pos: 0,
9844 orig_loc,
9845 }
9846 }
9847 pub fn get_buf(&self) -> &'a [u8] {
9848 self.buf
9849 }
9850}
9851impl<'a> Iterator for IterableOpQueueGetDoReply<'a> {
9852 type Item = Result<OpQueueGetDoReply<'a>, ErrorContext>;
9853 fn next(&mut self) -> Option<Self::Item> {
9854 let pos = self.pos;
9855 let mut r#type;
9856 loop {
9857 r#type = None;
9858 if self.buf.len() == self.pos {
9859 return None;
9860 }
9861 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
9862 break;
9863 };
9864 r#type = Some(header.r#type);
9865 let res = match header.r#type {
9866 1u16 => OpQueueGetDoReply::Id({
9867 let res = parse_u32(next);
9868 let Some(val) = res else { break };
9869 val
9870 }),
9871 2u16 => OpQueueGetDoReply::Ifindex({
9872 let res = parse_u32(next);
9873 let Some(val) = res else { break };
9874 val
9875 }),
9876 3u16 => OpQueueGetDoReply::Type({
9877 let res = parse_u32(next);
9878 let Some(val) = res else { break };
9879 val
9880 }),
9881 4u16 => OpQueueGetDoReply::NapiId({
9882 let res = parse_u32(next);
9883 let Some(val) = res else { break };
9884 val
9885 }),
9886 5u16 => OpQueueGetDoReply::Dmabuf({
9887 let res = parse_u32(next);
9888 let Some(val) = res else { break };
9889 val
9890 }),
9891 6u16 => OpQueueGetDoReply::IoUring({
9892 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9893 let Some(val) = res else { break };
9894 val
9895 }),
9896 7u16 => OpQueueGetDoReply::Xsk({
9897 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9898 let Some(val) = res else { break };
9899 val
9900 }),
9901 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
9902 n => continue,
9903 };
9904 return Some(Ok(res));
9905 }
9906 Some(Err(ErrorContext::new(
9907 "OpQueueGetDoReply",
9908 r#type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9909 self.orig_loc,
9910 self.buf.as_ptr().wrapping_add(pos) as usize,
9911 )))
9912 }
9913}
9914impl<'a> std::fmt::Debug for IterableOpQueueGetDoReply<'_> {
9915 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9916 let mut fmt = f.debug_struct("OpQueueGetDoReply");
9917 for attr in self.clone() {
9918 let attr = match attr {
9919 Ok(a) => a,
9920 Err(err) => {
9921 fmt.finish()?;
9922 f.write_str("Err(")?;
9923 err.fmt(f)?;
9924 return f.write_str(")");
9925 }
9926 };
9927 match attr {
9928 OpQueueGetDoReply::Id(val) => fmt.field("Id", &val),
9929 OpQueueGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
9930 OpQueueGetDoReply::Type(val) => {
9931 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9932 }
9933 OpQueueGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
9934 OpQueueGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9935 OpQueueGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
9936 OpQueueGetDoReply::Xsk(val) => fmt.field("Xsk", &val),
9937 };
9938 }
9939 fmt.finish()
9940 }
9941}
9942impl IterableOpQueueGetDoReply<'_> {
9943 pub fn lookup_attr(
9944 &self,
9945 offset: usize,
9946 missing_type: Option<u16>,
9947 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9948 let mut stack = Vec::new();
9949 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9950 if cur == offset + PushBuiltinNfgenmsg::len() {
9951 stack.push(("OpQueueGetDoReply", offset));
9952 return (
9953 stack,
9954 missing_type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9955 );
9956 }
9957 if cur > offset || cur + self.buf.len() < offset {
9958 return (stack, None);
9959 }
9960 let mut attrs = self.clone();
9961 let mut last_off = cur + attrs.pos;
9962 let mut missing = None;
9963 while let Some(attr) = attrs.next() {
9964 let Ok(attr) = attr else { break };
9965 match attr {
9966 OpQueueGetDoReply::Id(val) => {
9967 if last_off == offset {
9968 stack.push(("Id", last_off));
9969 break;
9970 }
9971 }
9972 OpQueueGetDoReply::Ifindex(val) => {
9973 if last_off == offset {
9974 stack.push(("Ifindex", last_off));
9975 break;
9976 }
9977 }
9978 OpQueueGetDoReply::Type(val) => {
9979 if last_off == offset {
9980 stack.push(("Type", last_off));
9981 break;
9982 }
9983 }
9984 OpQueueGetDoReply::NapiId(val) => {
9985 if last_off == offset {
9986 stack.push(("NapiId", last_off));
9987 break;
9988 }
9989 }
9990 OpQueueGetDoReply::Dmabuf(val) => {
9991 if last_off == offset {
9992 stack.push(("Dmabuf", last_off));
9993 break;
9994 }
9995 }
9996 OpQueueGetDoReply::IoUring(val) => {
9997 (stack, missing) = val.lookup_attr(offset, missing_type);
9998 if !stack.is_empty() {
9999 break;
10000 }
10001 }
10002 OpQueueGetDoReply::Xsk(val) => {
10003 (stack, missing) = val.lookup_attr(offset, missing_type);
10004 if !stack.is_empty() {
10005 break;
10006 }
10007 }
10008 _ => {}
10009 };
10010 last_off = cur + attrs.pos;
10011 }
10012 if !stack.is_empty() {
10013 stack.push(("OpQueueGetDoReply", cur));
10014 }
10015 (stack, missing)
10016 }
10017}
10018#[derive(Debug)]
10019pub struct RequestOpQueueGetDoRequest<'r> {
10020 request: Request<'r>,
10021}
10022impl<'r> RequestOpQueueGetDoRequest<'r> {
10023 pub fn new(mut request: Request<'r>) -> Self {
10024 PushOpQueueGetDoRequest::write_header(&mut request.buf_mut());
10025 Self { request: request }
10026 }
10027 pub fn encode(&mut self) -> PushOpQueueGetDoRequest<&mut Vec<u8>> {
10028 PushOpQueueGetDoRequest::new_without_header(self.request.buf_mut())
10029 }
10030 pub fn into_encoder(self) -> PushOpQueueGetDoRequest<RequestBuf<'r>> {
10031 PushOpQueueGetDoRequest::new_without_header(self.request.buf)
10032 }
10033 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQueueGetDoRequest<'buf> {
10034 OpQueueGetDoRequest::new(buf)
10035 }
10036}
10037impl NetlinkRequest for RequestOpQueueGetDoRequest<'_> {
10038 fn protocol(&self) -> Protocol {
10039 Protocol::Generic("netdev".as_bytes())
10040 }
10041 fn flags(&self) -> u16 {
10042 self.request.flags
10043 }
10044 fn payload(&self) -> &[u8] {
10045 self.request.buf()
10046 }
10047 type ReplyType<'buf> = IterableOpQueueGetDoReply<'buf>;
10048 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10049 OpQueueGetDoReply::new(buf)
10050 }
10051 fn lookup(
10052 buf: &[u8],
10053 offset: usize,
10054 missing_type: Option<u16>,
10055 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10056 OpQueueGetDoRequest::new(buf).lookup_attr(offset, missing_type)
10057 }
10058}
10059#[doc = "Get information about NAPI instances configured on the system."]
10060pub struct PushOpNapiGetDumpRequest<Prev: Rec> {
10061 pub(crate) prev: Option<Prev>,
10062 pub(crate) header_offset: Option<usize>,
10063}
10064impl<Prev: Rec> Rec for PushOpNapiGetDumpRequest<Prev> {
10065 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10066 self.prev.as_mut().unwrap().as_rec_mut()
10067 }
10068 fn as_rec(&self) -> &Vec<u8> {
10069 self.prev.as_ref().unwrap().as_rec()
10070 }
10071}
10072impl<Prev: Rec> PushOpNapiGetDumpRequest<Prev> {
10073 pub fn new(mut prev: Prev) -> Self {
10074 Self::write_header(&mut prev);
10075 Self::new_without_header(prev)
10076 }
10077 fn new_without_header(prev: Prev) -> Self {
10078 Self {
10079 prev: Some(prev),
10080 header_offset: None,
10081 }
10082 }
10083 fn write_header(prev: &mut Prev) {
10084 let mut header = PushBuiltinNfgenmsg::new();
10085 header.set_cmd(11u8);
10086 header.set_version(1u8);
10087 prev.as_rec_mut().extend(header.as_slice());
10088 }
10089 pub fn end_nested(mut self) -> Prev {
10090 let mut prev = self.prev.take().unwrap();
10091 if let Some(header_offset) = &self.header_offset {
10092 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10093 }
10094 prev
10095 }
10096 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10097 pub fn push_ifindex(mut self, value: u32) -> Self {
10098 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10099 self.as_rec_mut().extend(value.to_ne_bytes());
10100 self
10101 }
10102}
10103impl<Prev: Rec> Drop for PushOpNapiGetDumpRequest<Prev> {
10104 fn drop(&mut self) {
10105 if let Some(prev) = &mut self.prev {
10106 if let Some(header_offset) = &self.header_offset {
10107 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10108 }
10109 }
10110 }
10111}
10112#[doc = "Get information about NAPI instances configured on the system."]
10113#[derive(Clone)]
10114pub enum OpNapiGetDumpRequest {
10115 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10116 Ifindex(u32),
10117}
10118impl<'a> IterableOpNapiGetDumpRequest<'a> {
10119 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10120 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10121 let mut iter = self.clone();
10122 iter.pos = 0;
10123 for attr in iter {
10124 if let OpNapiGetDumpRequest::Ifindex(val) = attr? {
10125 return Ok(val);
10126 }
10127 }
10128 Err(ErrorContext::new_missing(
10129 "OpNapiGetDumpRequest",
10130 "Ifindex",
10131 self.orig_loc,
10132 self.buf.as_ptr() as usize,
10133 ))
10134 }
10135}
10136impl OpNapiGetDumpRequest {
10137 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpRequest<'a> {
10138 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10139 IterableOpNapiGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
10140 }
10141 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10142 Napi::attr_from_type(r#type)
10143 }
10144}
10145#[derive(Clone, Copy, Default)]
10146pub struct IterableOpNapiGetDumpRequest<'a> {
10147 buf: &'a [u8],
10148 pos: usize,
10149 orig_loc: usize,
10150}
10151impl<'a> IterableOpNapiGetDumpRequest<'a> {
10152 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10153 Self {
10154 buf,
10155 pos: 0,
10156 orig_loc,
10157 }
10158 }
10159 pub fn get_buf(&self) -> &'a [u8] {
10160 self.buf
10161 }
10162}
10163impl<'a> Iterator for IterableOpNapiGetDumpRequest<'a> {
10164 type Item = Result<OpNapiGetDumpRequest, ErrorContext>;
10165 fn next(&mut self) -> Option<Self::Item> {
10166 let pos = self.pos;
10167 let mut r#type;
10168 loop {
10169 r#type = None;
10170 if self.buf.len() == self.pos {
10171 return None;
10172 }
10173 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10174 break;
10175 };
10176 r#type = Some(header.r#type);
10177 let res = match header.r#type {
10178 1u16 => OpNapiGetDumpRequest::Ifindex({
10179 let res = parse_u32(next);
10180 let Some(val) = res else { break };
10181 val
10182 }),
10183 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10184 n => continue,
10185 };
10186 return Some(Ok(res));
10187 }
10188 Some(Err(ErrorContext::new(
10189 "OpNapiGetDumpRequest",
10190 r#type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10191 self.orig_loc,
10192 self.buf.as_ptr().wrapping_add(pos) as usize,
10193 )))
10194 }
10195}
10196impl std::fmt::Debug for IterableOpNapiGetDumpRequest<'_> {
10197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10198 let mut fmt = f.debug_struct("OpNapiGetDumpRequest");
10199 for attr in self.clone() {
10200 let attr = match attr {
10201 Ok(a) => a,
10202 Err(err) => {
10203 fmt.finish()?;
10204 f.write_str("Err(")?;
10205 err.fmt(f)?;
10206 return f.write_str(")");
10207 }
10208 };
10209 match attr {
10210 OpNapiGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
10211 };
10212 }
10213 fmt.finish()
10214 }
10215}
10216impl IterableOpNapiGetDumpRequest<'_> {
10217 pub fn lookup_attr(
10218 &self,
10219 offset: usize,
10220 missing_type: Option<u16>,
10221 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10222 let mut stack = Vec::new();
10223 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10224 if cur == offset + PushBuiltinNfgenmsg::len() {
10225 stack.push(("OpNapiGetDumpRequest", offset));
10226 return (
10227 stack,
10228 missing_type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10229 );
10230 }
10231 if cur > offset || cur + self.buf.len() < offset {
10232 return (stack, None);
10233 }
10234 let mut attrs = self.clone();
10235 let mut last_off = cur + attrs.pos;
10236 while let Some(attr) = attrs.next() {
10237 let Ok(attr) = attr else { break };
10238 match attr {
10239 OpNapiGetDumpRequest::Ifindex(val) => {
10240 if last_off == offset {
10241 stack.push(("Ifindex", last_off));
10242 break;
10243 }
10244 }
10245 _ => {}
10246 };
10247 last_off = cur + attrs.pos;
10248 }
10249 if !stack.is_empty() {
10250 stack.push(("OpNapiGetDumpRequest", cur));
10251 }
10252 (stack, None)
10253 }
10254}
10255#[doc = "Get information about NAPI instances configured on the system."]
10256pub struct PushOpNapiGetDumpReply<Prev: Rec> {
10257 pub(crate) prev: Option<Prev>,
10258 pub(crate) header_offset: Option<usize>,
10259}
10260impl<Prev: Rec> Rec for PushOpNapiGetDumpReply<Prev> {
10261 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10262 self.prev.as_mut().unwrap().as_rec_mut()
10263 }
10264 fn as_rec(&self) -> &Vec<u8> {
10265 self.prev.as_ref().unwrap().as_rec()
10266 }
10267}
10268impl<Prev: Rec> PushOpNapiGetDumpReply<Prev> {
10269 pub fn new(mut prev: Prev) -> Self {
10270 Self::write_header(&mut prev);
10271 Self::new_without_header(prev)
10272 }
10273 fn new_without_header(prev: Prev) -> Self {
10274 Self {
10275 prev: Some(prev),
10276 header_offset: None,
10277 }
10278 }
10279 fn write_header(prev: &mut Prev) {
10280 let mut header = PushBuiltinNfgenmsg::new();
10281 header.set_cmd(11u8);
10282 header.set_version(1u8);
10283 prev.as_rec_mut().extend(header.as_slice());
10284 }
10285 pub fn end_nested(mut self) -> Prev {
10286 let mut prev = self.prev.take().unwrap();
10287 if let Some(header_offset) = &self.header_offset {
10288 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10289 }
10290 prev
10291 }
10292 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10293 pub fn push_ifindex(mut self, value: u32) -> Self {
10294 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10295 self.as_rec_mut().extend(value.to_ne_bytes());
10296 self
10297 }
10298 #[doc = "ID of the NAPI instance."]
10299 pub fn push_id(mut self, value: u32) -> Self {
10300 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10301 self.as_rec_mut().extend(value.to_ne_bytes());
10302 self
10303 }
10304 #[doc = "The associated interrupt vector number for the napi"]
10305 pub fn push_irq(mut self, value: u32) -> Self {
10306 push_header(self.as_rec_mut(), 3u16, 4 as u16);
10307 self.as_rec_mut().extend(value.to_ne_bytes());
10308 self
10309 }
10310 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10311 pub fn push_pid(mut self, value: u32) -> Self {
10312 push_header(self.as_rec_mut(), 4u16, 4 as u16);
10313 self.as_rec_mut().extend(value.to_ne_bytes());
10314 self
10315 }
10316 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10317 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10318 push_header(self.as_rec_mut(), 5u16, 4 as u16);
10319 self.as_rec_mut().extend(value.to_ne_bytes());
10320 self
10321 }
10322 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10323 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10324 push_header(self.as_rec_mut(), 6u16, 4 as u16);
10325 self.as_rec_mut().extend(value.to_ne_bytes());
10326 self
10327 }
10328 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10329 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10330 push_header(self.as_rec_mut(), 7u16, 4 as u16);
10331 self.as_rec_mut().extend(value.to_ne_bytes());
10332 self
10333 }
10334 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10335 pub fn push_threaded(mut self, value: u32) -> Self {
10336 push_header(self.as_rec_mut(), 8u16, 4 as u16);
10337 self.as_rec_mut().extend(value.to_ne_bytes());
10338 self
10339 }
10340}
10341impl<Prev: Rec> Drop for PushOpNapiGetDumpReply<Prev> {
10342 fn drop(&mut self) {
10343 if let Some(prev) = &mut self.prev {
10344 if let Some(header_offset) = &self.header_offset {
10345 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10346 }
10347 }
10348 }
10349}
10350#[doc = "Get information about NAPI instances configured on the system."]
10351#[derive(Clone)]
10352pub enum OpNapiGetDumpReply {
10353 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10354 Ifindex(u32),
10355 #[doc = "ID of the NAPI instance."]
10356 Id(u32),
10357 #[doc = "The associated interrupt vector number for the napi"]
10358 Irq(u32),
10359 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10360 Pid(u32),
10361 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10362 DeferHardIrqs(u32),
10363 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10364 GroFlushTimeout(u32),
10365 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10366 IrqSuspendTimeout(u32),
10367 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10368 Threaded(u32),
10369}
10370impl<'a> IterableOpNapiGetDumpReply<'a> {
10371 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10372 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10373 let mut iter = self.clone();
10374 iter.pos = 0;
10375 for attr in iter {
10376 if let OpNapiGetDumpReply::Ifindex(val) = attr? {
10377 return Ok(val);
10378 }
10379 }
10380 Err(ErrorContext::new_missing(
10381 "OpNapiGetDumpReply",
10382 "Ifindex",
10383 self.orig_loc,
10384 self.buf.as_ptr() as usize,
10385 ))
10386 }
10387 #[doc = "ID of the NAPI instance."]
10388 pub fn get_id(&self) -> Result<u32, ErrorContext> {
10389 let mut iter = self.clone();
10390 iter.pos = 0;
10391 for attr in iter {
10392 if let OpNapiGetDumpReply::Id(val) = attr? {
10393 return Ok(val);
10394 }
10395 }
10396 Err(ErrorContext::new_missing(
10397 "OpNapiGetDumpReply",
10398 "Id",
10399 self.orig_loc,
10400 self.buf.as_ptr() as usize,
10401 ))
10402 }
10403 #[doc = "The associated interrupt vector number for the napi"]
10404 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
10405 let mut iter = self.clone();
10406 iter.pos = 0;
10407 for attr in iter {
10408 if let OpNapiGetDumpReply::Irq(val) = attr? {
10409 return Ok(val);
10410 }
10411 }
10412 Err(ErrorContext::new_missing(
10413 "OpNapiGetDumpReply",
10414 "Irq",
10415 self.orig_loc,
10416 self.buf.as_ptr() as usize,
10417 ))
10418 }
10419 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
10420 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
10421 let mut iter = self.clone();
10422 iter.pos = 0;
10423 for attr in iter {
10424 if let OpNapiGetDumpReply::Pid(val) = attr? {
10425 return Ok(val);
10426 }
10427 }
10428 Err(ErrorContext::new_missing(
10429 "OpNapiGetDumpReply",
10430 "Pid",
10431 self.orig_loc,
10432 self.buf.as_ptr() as usize,
10433 ))
10434 }
10435 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10436 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
10437 let mut iter = self.clone();
10438 iter.pos = 0;
10439 for attr in iter {
10440 if let OpNapiGetDumpReply::DeferHardIrqs(val) = attr? {
10441 return Ok(val);
10442 }
10443 }
10444 Err(ErrorContext::new_missing(
10445 "OpNapiGetDumpReply",
10446 "DeferHardIrqs",
10447 self.orig_loc,
10448 self.buf.as_ptr() as usize,
10449 ))
10450 }
10451 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
10452 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
10453 let mut iter = self.clone();
10454 iter.pos = 0;
10455 for attr in iter {
10456 if let OpNapiGetDumpReply::GroFlushTimeout(val) = attr? {
10457 return Ok(val);
10458 }
10459 }
10460 Err(ErrorContext::new_missing(
10461 "OpNapiGetDumpReply",
10462 "GroFlushTimeout",
10463 self.orig_loc,
10464 self.buf.as_ptr() as usize,
10465 ))
10466 }
10467 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10468 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
10469 let mut iter = self.clone();
10470 iter.pos = 0;
10471 for attr in iter {
10472 if let OpNapiGetDumpReply::IrqSuspendTimeout(val) = attr? {
10473 return Ok(val);
10474 }
10475 }
10476 Err(ErrorContext::new_missing(
10477 "OpNapiGetDumpReply",
10478 "IrqSuspendTimeout",
10479 self.orig_loc,
10480 self.buf.as_ptr() as usize,
10481 ))
10482 }
10483 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
10484 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
10485 let mut iter = self.clone();
10486 iter.pos = 0;
10487 for attr in iter {
10488 if let OpNapiGetDumpReply::Threaded(val) = attr? {
10489 return Ok(val);
10490 }
10491 }
10492 Err(ErrorContext::new_missing(
10493 "OpNapiGetDumpReply",
10494 "Threaded",
10495 self.orig_loc,
10496 self.buf.as_ptr() as usize,
10497 ))
10498 }
10499}
10500impl OpNapiGetDumpReply {
10501 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpReply<'a> {
10502 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10503 IterableOpNapiGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
10504 }
10505 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10506 Napi::attr_from_type(r#type)
10507 }
10508}
10509#[derive(Clone, Copy, Default)]
10510pub struct IterableOpNapiGetDumpReply<'a> {
10511 buf: &'a [u8],
10512 pos: usize,
10513 orig_loc: usize,
10514}
10515impl<'a> IterableOpNapiGetDumpReply<'a> {
10516 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10517 Self {
10518 buf,
10519 pos: 0,
10520 orig_loc,
10521 }
10522 }
10523 pub fn get_buf(&self) -> &'a [u8] {
10524 self.buf
10525 }
10526}
10527impl<'a> Iterator for IterableOpNapiGetDumpReply<'a> {
10528 type Item = Result<OpNapiGetDumpReply, ErrorContext>;
10529 fn next(&mut self) -> Option<Self::Item> {
10530 let pos = self.pos;
10531 let mut r#type;
10532 loop {
10533 r#type = None;
10534 if self.buf.len() == self.pos {
10535 return None;
10536 }
10537 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10538 break;
10539 };
10540 r#type = Some(header.r#type);
10541 let res = match header.r#type {
10542 1u16 => OpNapiGetDumpReply::Ifindex({
10543 let res = parse_u32(next);
10544 let Some(val) = res else { break };
10545 val
10546 }),
10547 2u16 => OpNapiGetDumpReply::Id({
10548 let res = parse_u32(next);
10549 let Some(val) = res else { break };
10550 val
10551 }),
10552 3u16 => OpNapiGetDumpReply::Irq({
10553 let res = parse_u32(next);
10554 let Some(val) = res else { break };
10555 val
10556 }),
10557 4u16 => OpNapiGetDumpReply::Pid({
10558 let res = parse_u32(next);
10559 let Some(val) = res else { break };
10560 val
10561 }),
10562 5u16 => OpNapiGetDumpReply::DeferHardIrqs({
10563 let res = parse_u32(next);
10564 let Some(val) = res else { break };
10565 val
10566 }),
10567 6u16 => OpNapiGetDumpReply::GroFlushTimeout({
10568 let res = parse_u32(next);
10569 let Some(val) = res else { break };
10570 val
10571 }),
10572 7u16 => OpNapiGetDumpReply::IrqSuspendTimeout({
10573 let res = parse_u32(next);
10574 let Some(val) = res else { break };
10575 val
10576 }),
10577 8u16 => OpNapiGetDumpReply::Threaded({
10578 let res = parse_u32(next);
10579 let Some(val) = res else { break };
10580 val
10581 }),
10582 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10583 n => continue,
10584 };
10585 return Some(Ok(res));
10586 }
10587 Some(Err(ErrorContext::new(
10588 "OpNapiGetDumpReply",
10589 r#type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10590 self.orig_loc,
10591 self.buf.as_ptr().wrapping_add(pos) as usize,
10592 )))
10593 }
10594}
10595impl std::fmt::Debug for IterableOpNapiGetDumpReply<'_> {
10596 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10597 let mut fmt = f.debug_struct("OpNapiGetDumpReply");
10598 for attr in self.clone() {
10599 let attr = match attr {
10600 Ok(a) => a,
10601 Err(err) => {
10602 fmt.finish()?;
10603 f.write_str("Err(")?;
10604 err.fmt(f)?;
10605 return f.write_str(")");
10606 }
10607 };
10608 match attr {
10609 OpNapiGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
10610 OpNapiGetDumpReply::Id(val) => fmt.field("Id", &val),
10611 OpNapiGetDumpReply::Irq(val) => fmt.field("Irq", &val),
10612 OpNapiGetDumpReply::Pid(val) => fmt.field("Pid", &val),
10613 OpNapiGetDumpReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
10614 OpNapiGetDumpReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
10615 OpNapiGetDumpReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
10616 OpNapiGetDumpReply::Threaded(val) => fmt.field(
10617 "Threaded",
10618 &FormatEnum(val.into(), NapiThreaded::from_value),
10619 ),
10620 };
10621 }
10622 fmt.finish()
10623 }
10624}
10625impl IterableOpNapiGetDumpReply<'_> {
10626 pub fn lookup_attr(
10627 &self,
10628 offset: usize,
10629 missing_type: Option<u16>,
10630 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10631 let mut stack = Vec::new();
10632 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10633 if cur == offset + PushBuiltinNfgenmsg::len() {
10634 stack.push(("OpNapiGetDumpReply", offset));
10635 return (
10636 stack,
10637 missing_type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10638 );
10639 }
10640 if cur > offset || cur + self.buf.len() < offset {
10641 return (stack, None);
10642 }
10643 let mut attrs = self.clone();
10644 let mut last_off = cur + attrs.pos;
10645 while let Some(attr) = attrs.next() {
10646 let Ok(attr) = attr else { break };
10647 match attr {
10648 OpNapiGetDumpReply::Ifindex(val) => {
10649 if last_off == offset {
10650 stack.push(("Ifindex", last_off));
10651 break;
10652 }
10653 }
10654 OpNapiGetDumpReply::Id(val) => {
10655 if last_off == offset {
10656 stack.push(("Id", last_off));
10657 break;
10658 }
10659 }
10660 OpNapiGetDumpReply::Irq(val) => {
10661 if last_off == offset {
10662 stack.push(("Irq", last_off));
10663 break;
10664 }
10665 }
10666 OpNapiGetDumpReply::Pid(val) => {
10667 if last_off == offset {
10668 stack.push(("Pid", last_off));
10669 break;
10670 }
10671 }
10672 OpNapiGetDumpReply::DeferHardIrqs(val) => {
10673 if last_off == offset {
10674 stack.push(("DeferHardIrqs", last_off));
10675 break;
10676 }
10677 }
10678 OpNapiGetDumpReply::GroFlushTimeout(val) => {
10679 if last_off == offset {
10680 stack.push(("GroFlushTimeout", last_off));
10681 break;
10682 }
10683 }
10684 OpNapiGetDumpReply::IrqSuspendTimeout(val) => {
10685 if last_off == offset {
10686 stack.push(("IrqSuspendTimeout", last_off));
10687 break;
10688 }
10689 }
10690 OpNapiGetDumpReply::Threaded(val) => {
10691 if last_off == offset {
10692 stack.push(("Threaded", last_off));
10693 break;
10694 }
10695 }
10696 _ => {}
10697 };
10698 last_off = cur + attrs.pos;
10699 }
10700 if !stack.is_empty() {
10701 stack.push(("OpNapiGetDumpReply", cur));
10702 }
10703 (stack, None)
10704 }
10705}
10706#[derive(Debug)]
10707pub struct RequestOpNapiGetDumpRequest<'r> {
10708 request: Request<'r>,
10709}
10710impl<'r> RequestOpNapiGetDumpRequest<'r> {
10711 pub fn new(mut request: Request<'r>) -> Self {
10712 PushOpNapiGetDumpRequest::write_header(&mut request.buf_mut());
10713 Self {
10714 request: request.set_dump(),
10715 }
10716 }
10717 pub fn encode(&mut self) -> PushOpNapiGetDumpRequest<&mut Vec<u8>> {
10718 PushOpNapiGetDumpRequest::new_without_header(self.request.buf_mut())
10719 }
10720 pub fn into_encoder(self) -> PushOpNapiGetDumpRequest<RequestBuf<'r>> {
10721 PushOpNapiGetDumpRequest::new_without_header(self.request.buf)
10722 }
10723 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiGetDumpRequest<'buf> {
10724 OpNapiGetDumpRequest::new(buf)
10725 }
10726}
10727impl NetlinkRequest for RequestOpNapiGetDumpRequest<'_> {
10728 fn protocol(&self) -> Protocol {
10729 Protocol::Generic("netdev".as_bytes())
10730 }
10731 fn flags(&self) -> u16 {
10732 self.request.flags
10733 }
10734 fn payload(&self) -> &[u8] {
10735 self.request.buf()
10736 }
10737 type ReplyType<'buf> = IterableOpNapiGetDumpReply<'buf>;
10738 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10739 OpNapiGetDumpReply::new(buf)
10740 }
10741 fn lookup(
10742 buf: &[u8],
10743 offset: usize,
10744 missing_type: Option<u16>,
10745 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10746 OpNapiGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
10747 }
10748}
10749#[doc = "Get information about NAPI instances configured on the system."]
10750pub struct PushOpNapiGetDoRequest<Prev: Rec> {
10751 pub(crate) prev: Option<Prev>,
10752 pub(crate) header_offset: Option<usize>,
10753}
10754impl<Prev: Rec> Rec for PushOpNapiGetDoRequest<Prev> {
10755 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10756 self.prev.as_mut().unwrap().as_rec_mut()
10757 }
10758 fn as_rec(&self) -> &Vec<u8> {
10759 self.prev.as_ref().unwrap().as_rec()
10760 }
10761}
10762impl<Prev: Rec> PushOpNapiGetDoRequest<Prev> {
10763 pub fn new(mut prev: Prev) -> Self {
10764 Self::write_header(&mut prev);
10765 Self::new_without_header(prev)
10766 }
10767 fn new_without_header(prev: Prev) -> Self {
10768 Self {
10769 prev: Some(prev),
10770 header_offset: None,
10771 }
10772 }
10773 fn write_header(prev: &mut Prev) {
10774 let mut header = PushBuiltinNfgenmsg::new();
10775 header.set_cmd(11u8);
10776 header.set_version(1u8);
10777 prev.as_rec_mut().extend(header.as_slice());
10778 }
10779 pub fn end_nested(mut self) -> Prev {
10780 let mut prev = self.prev.take().unwrap();
10781 if let Some(header_offset) = &self.header_offset {
10782 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10783 }
10784 prev
10785 }
10786 #[doc = "ID of the NAPI instance."]
10787 pub fn push_id(mut self, value: u32) -> Self {
10788 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10789 self.as_rec_mut().extend(value.to_ne_bytes());
10790 self
10791 }
10792}
10793impl<Prev: Rec> Drop for PushOpNapiGetDoRequest<Prev> {
10794 fn drop(&mut self) {
10795 if let Some(prev) = &mut self.prev {
10796 if let Some(header_offset) = &self.header_offset {
10797 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10798 }
10799 }
10800 }
10801}
10802#[doc = "Get information about NAPI instances configured on the system."]
10803#[derive(Clone)]
10804pub enum OpNapiGetDoRequest {
10805 #[doc = "ID of the NAPI instance."]
10806 Id(u32),
10807}
10808impl<'a> IterableOpNapiGetDoRequest<'a> {
10809 #[doc = "ID of the NAPI instance."]
10810 pub fn get_id(&self) -> Result<u32, ErrorContext> {
10811 let mut iter = self.clone();
10812 iter.pos = 0;
10813 for attr in iter {
10814 if let OpNapiGetDoRequest::Id(val) = attr? {
10815 return Ok(val);
10816 }
10817 }
10818 Err(ErrorContext::new_missing(
10819 "OpNapiGetDoRequest",
10820 "Id",
10821 self.orig_loc,
10822 self.buf.as_ptr() as usize,
10823 ))
10824 }
10825}
10826impl OpNapiGetDoRequest {
10827 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoRequest<'a> {
10828 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10829 IterableOpNapiGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
10830 }
10831 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10832 Napi::attr_from_type(r#type)
10833 }
10834}
10835#[derive(Clone, Copy, Default)]
10836pub struct IterableOpNapiGetDoRequest<'a> {
10837 buf: &'a [u8],
10838 pos: usize,
10839 orig_loc: usize,
10840}
10841impl<'a> IterableOpNapiGetDoRequest<'a> {
10842 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10843 Self {
10844 buf,
10845 pos: 0,
10846 orig_loc,
10847 }
10848 }
10849 pub fn get_buf(&self) -> &'a [u8] {
10850 self.buf
10851 }
10852}
10853impl<'a> Iterator for IterableOpNapiGetDoRequest<'a> {
10854 type Item = Result<OpNapiGetDoRequest, ErrorContext>;
10855 fn next(&mut self) -> Option<Self::Item> {
10856 let pos = self.pos;
10857 let mut r#type;
10858 loop {
10859 r#type = None;
10860 if self.buf.len() == self.pos {
10861 return None;
10862 }
10863 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
10864 break;
10865 };
10866 r#type = Some(header.r#type);
10867 let res = match header.r#type {
10868 2u16 => OpNapiGetDoRequest::Id({
10869 let res = parse_u32(next);
10870 let Some(val) = res else { break };
10871 val
10872 }),
10873 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
10874 n => continue,
10875 };
10876 return Some(Ok(res));
10877 }
10878 Some(Err(ErrorContext::new(
10879 "OpNapiGetDoRequest",
10880 r#type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10881 self.orig_loc,
10882 self.buf.as_ptr().wrapping_add(pos) as usize,
10883 )))
10884 }
10885}
10886impl std::fmt::Debug for IterableOpNapiGetDoRequest<'_> {
10887 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10888 let mut fmt = f.debug_struct("OpNapiGetDoRequest");
10889 for attr in self.clone() {
10890 let attr = match attr {
10891 Ok(a) => a,
10892 Err(err) => {
10893 fmt.finish()?;
10894 f.write_str("Err(")?;
10895 err.fmt(f)?;
10896 return f.write_str(")");
10897 }
10898 };
10899 match attr {
10900 OpNapiGetDoRequest::Id(val) => fmt.field("Id", &val),
10901 };
10902 }
10903 fmt.finish()
10904 }
10905}
10906impl IterableOpNapiGetDoRequest<'_> {
10907 pub fn lookup_attr(
10908 &self,
10909 offset: usize,
10910 missing_type: Option<u16>,
10911 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10912 let mut stack = Vec::new();
10913 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10914 if cur == offset + PushBuiltinNfgenmsg::len() {
10915 stack.push(("OpNapiGetDoRequest", offset));
10916 return (
10917 stack,
10918 missing_type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10919 );
10920 }
10921 if cur > offset || cur + self.buf.len() < offset {
10922 return (stack, None);
10923 }
10924 let mut attrs = self.clone();
10925 let mut last_off = cur + attrs.pos;
10926 while let Some(attr) = attrs.next() {
10927 let Ok(attr) = attr else { break };
10928 match attr {
10929 OpNapiGetDoRequest::Id(val) => {
10930 if last_off == offset {
10931 stack.push(("Id", last_off));
10932 break;
10933 }
10934 }
10935 _ => {}
10936 };
10937 last_off = cur + attrs.pos;
10938 }
10939 if !stack.is_empty() {
10940 stack.push(("OpNapiGetDoRequest", cur));
10941 }
10942 (stack, None)
10943 }
10944}
10945#[doc = "Get information about NAPI instances configured on the system."]
10946pub struct PushOpNapiGetDoReply<Prev: Rec> {
10947 pub(crate) prev: Option<Prev>,
10948 pub(crate) header_offset: Option<usize>,
10949}
10950impl<Prev: Rec> Rec for PushOpNapiGetDoReply<Prev> {
10951 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10952 self.prev.as_mut().unwrap().as_rec_mut()
10953 }
10954 fn as_rec(&self) -> &Vec<u8> {
10955 self.prev.as_ref().unwrap().as_rec()
10956 }
10957}
10958impl<Prev: Rec> PushOpNapiGetDoReply<Prev> {
10959 pub fn new(mut prev: Prev) -> Self {
10960 Self::write_header(&mut prev);
10961 Self::new_without_header(prev)
10962 }
10963 fn new_without_header(prev: Prev) -> Self {
10964 Self {
10965 prev: Some(prev),
10966 header_offset: None,
10967 }
10968 }
10969 fn write_header(prev: &mut Prev) {
10970 let mut header = PushBuiltinNfgenmsg::new();
10971 header.set_cmd(11u8);
10972 header.set_version(1u8);
10973 prev.as_rec_mut().extend(header.as_slice());
10974 }
10975 pub fn end_nested(mut self) -> Prev {
10976 let mut prev = self.prev.take().unwrap();
10977 if let Some(header_offset) = &self.header_offset {
10978 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10979 }
10980 prev
10981 }
10982 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10983 pub fn push_ifindex(mut self, value: u32) -> Self {
10984 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10985 self.as_rec_mut().extend(value.to_ne_bytes());
10986 self
10987 }
10988 #[doc = "ID of the NAPI instance."]
10989 pub fn push_id(mut self, value: u32) -> Self {
10990 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10991 self.as_rec_mut().extend(value.to_ne_bytes());
10992 self
10993 }
10994 #[doc = "The associated interrupt vector number for the napi"]
10995 pub fn push_irq(mut self, value: u32) -> Self {
10996 push_header(self.as_rec_mut(), 3u16, 4 as u16);
10997 self.as_rec_mut().extend(value.to_ne_bytes());
10998 self
10999 }
11000 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11001 pub fn push_pid(mut self, value: u32) -> Self {
11002 push_header(self.as_rec_mut(), 4u16, 4 as u16);
11003 self.as_rec_mut().extend(value.to_ne_bytes());
11004 self
11005 }
11006 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11007 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
11008 push_header(self.as_rec_mut(), 5u16, 4 as u16);
11009 self.as_rec_mut().extend(value.to_ne_bytes());
11010 self
11011 }
11012 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11013 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
11014 push_header(self.as_rec_mut(), 6u16, 4 as u16);
11015 self.as_rec_mut().extend(value.to_ne_bytes());
11016 self
11017 }
11018 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11019 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
11020 push_header(self.as_rec_mut(), 7u16, 4 as u16);
11021 self.as_rec_mut().extend(value.to_ne_bytes());
11022 self
11023 }
11024 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11025 pub fn push_threaded(mut self, value: u32) -> Self {
11026 push_header(self.as_rec_mut(), 8u16, 4 as u16);
11027 self.as_rec_mut().extend(value.to_ne_bytes());
11028 self
11029 }
11030}
11031impl<Prev: Rec> Drop for PushOpNapiGetDoReply<Prev> {
11032 fn drop(&mut self) {
11033 if let Some(prev) = &mut self.prev {
11034 if let Some(header_offset) = &self.header_offset {
11035 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11036 }
11037 }
11038 }
11039}
11040#[doc = "Get information about NAPI instances configured on the system."]
11041#[derive(Clone)]
11042pub enum OpNapiGetDoReply {
11043 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
11044 Ifindex(u32),
11045 #[doc = "ID of the NAPI instance."]
11046 Id(u32),
11047 #[doc = "The associated interrupt vector number for the napi"]
11048 Irq(u32),
11049 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11050 Pid(u32),
11051 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11052 DeferHardIrqs(u32),
11053 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11054 GroFlushTimeout(u32),
11055 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11056 IrqSuspendTimeout(u32),
11057 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11058 Threaded(u32),
11059}
11060impl<'a> IterableOpNapiGetDoReply<'a> {
11061 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
11062 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11063 let mut iter = self.clone();
11064 iter.pos = 0;
11065 for attr in iter {
11066 if let OpNapiGetDoReply::Ifindex(val) = attr? {
11067 return Ok(val);
11068 }
11069 }
11070 Err(ErrorContext::new_missing(
11071 "OpNapiGetDoReply",
11072 "Ifindex",
11073 self.orig_loc,
11074 self.buf.as_ptr() as usize,
11075 ))
11076 }
11077 #[doc = "ID of the NAPI instance."]
11078 pub fn get_id(&self) -> Result<u32, ErrorContext> {
11079 let mut iter = self.clone();
11080 iter.pos = 0;
11081 for attr in iter {
11082 if let OpNapiGetDoReply::Id(val) = attr? {
11083 return Ok(val);
11084 }
11085 }
11086 Err(ErrorContext::new_missing(
11087 "OpNapiGetDoReply",
11088 "Id",
11089 self.orig_loc,
11090 self.buf.as_ptr() as usize,
11091 ))
11092 }
11093 #[doc = "The associated interrupt vector number for the napi"]
11094 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
11095 let mut iter = self.clone();
11096 iter.pos = 0;
11097 for attr in iter {
11098 if let OpNapiGetDoReply::Irq(val) = attr? {
11099 return Ok(val);
11100 }
11101 }
11102 Err(ErrorContext::new_missing(
11103 "OpNapiGetDoReply",
11104 "Irq",
11105 self.orig_loc,
11106 self.buf.as_ptr() as usize,
11107 ))
11108 }
11109 #[doc = "PID of the napi thread, if NAPI is configured to operate in threaded mode. If NAPI is not in threaded mode (i.e. uses normal softirq context), the attribute will be absent."]
11110 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
11111 let mut iter = self.clone();
11112 iter.pos = 0;
11113 for attr in iter {
11114 if let OpNapiGetDoReply::Pid(val) = attr? {
11115 return Ok(val);
11116 }
11117 }
11118 Err(ErrorContext::new_missing(
11119 "OpNapiGetDoReply",
11120 "Pid",
11121 self.orig_loc,
11122 self.buf.as_ptr() as usize,
11123 ))
11124 }
11125 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11126 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
11127 let mut iter = self.clone();
11128 iter.pos = 0;
11129 for attr in iter {
11130 if let OpNapiGetDoReply::DeferHardIrqs(val) = attr? {
11131 return Ok(val);
11132 }
11133 }
11134 Err(ErrorContext::new_missing(
11135 "OpNapiGetDoReply",
11136 "DeferHardIrqs",
11137 self.orig_loc,
11138 self.buf.as_ptr() as usize,
11139 ))
11140 }
11141 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
11142 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
11143 let mut iter = self.clone();
11144 iter.pos = 0;
11145 for attr in iter {
11146 if let OpNapiGetDoReply::GroFlushTimeout(val) = attr? {
11147 return Ok(val);
11148 }
11149 }
11150 Err(ErrorContext::new_missing(
11151 "OpNapiGetDoReply",
11152 "GroFlushTimeout",
11153 self.orig_loc,
11154 self.buf.as_ptr() as usize,
11155 ))
11156 }
11157 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11158 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
11159 let mut iter = self.clone();
11160 iter.pos = 0;
11161 for attr in iter {
11162 if let OpNapiGetDoReply::IrqSuspendTimeout(val) = attr? {
11163 return Ok(val);
11164 }
11165 }
11166 Err(ErrorContext::new_missing(
11167 "OpNapiGetDoReply",
11168 "IrqSuspendTimeout",
11169 self.orig_loc,
11170 self.buf.as_ptr() as usize,
11171 ))
11172 }
11173 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
11174 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
11175 let mut iter = self.clone();
11176 iter.pos = 0;
11177 for attr in iter {
11178 if let OpNapiGetDoReply::Threaded(val) = attr? {
11179 return Ok(val);
11180 }
11181 }
11182 Err(ErrorContext::new_missing(
11183 "OpNapiGetDoReply",
11184 "Threaded",
11185 self.orig_loc,
11186 self.buf.as_ptr() as usize,
11187 ))
11188 }
11189}
11190impl OpNapiGetDoReply {
11191 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoReply<'a> {
11192 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11193 IterableOpNapiGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
11194 }
11195 fn attr_from_type(r#type: u16) -> Option<&'static str> {
11196 Napi::attr_from_type(r#type)
11197 }
11198}
11199#[derive(Clone, Copy, Default)]
11200pub struct IterableOpNapiGetDoReply<'a> {
11201 buf: &'a [u8],
11202 pos: usize,
11203 orig_loc: usize,
11204}
11205impl<'a> IterableOpNapiGetDoReply<'a> {
11206 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11207 Self {
11208 buf,
11209 pos: 0,
11210 orig_loc,
11211 }
11212 }
11213 pub fn get_buf(&self) -> &'a [u8] {
11214 self.buf
11215 }
11216}
11217impl<'a> Iterator for IterableOpNapiGetDoReply<'a> {
11218 type Item = Result<OpNapiGetDoReply, ErrorContext>;
11219 fn next(&mut self) -> Option<Self::Item> {
11220 let pos = self.pos;
11221 let mut r#type;
11222 loop {
11223 r#type = None;
11224 if self.buf.len() == self.pos {
11225 return None;
11226 }
11227 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
11228 break;
11229 };
11230 r#type = Some(header.r#type);
11231 let res = match header.r#type {
11232 1u16 => OpNapiGetDoReply::Ifindex({
11233 let res = parse_u32(next);
11234 let Some(val) = res else { break };
11235 val
11236 }),
11237 2u16 => OpNapiGetDoReply::Id({
11238 let res = parse_u32(next);
11239 let Some(val) = res else { break };
11240 val
11241 }),
11242 3u16 => OpNapiGetDoReply::Irq({
11243 let res = parse_u32(next);
11244 let Some(val) = res else { break };
11245 val
11246 }),
11247 4u16 => OpNapiGetDoReply::Pid({
11248 let res = parse_u32(next);
11249 let Some(val) = res else { break };
11250 val
11251 }),
11252 5u16 => OpNapiGetDoReply::DeferHardIrqs({
11253 let res = parse_u32(next);
11254 let Some(val) = res else { break };
11255 val
11256 }),
11257 6u16 => OpNapiGetDoReply::GroFlushTimeout({
11258 let res = parse_u32(next);
11259 let Some(val) = res else { break };
11260 val
11261 }),
11262 7u16 => OpNapiGetDoReply::IrqSuspendTimeout({
11263 let res = parse_u32(next);
11264 let Some(val) = res else { break };
11265 val
11266 }),
11267 8u16 => OpNapiGetDoReply::Threaded({
11268 let res = parse_u32(next);
11269 let Some(val) = res else { break };
11270 val
11271 }),
11272 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
11273 n => continue,
11274 };
11275 return Some(Ok(res));
11276 }
11277 Some(Err(ErrorContext::new(
11278 "OpNapiGetDoReply",
11279 r#type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11280 self.orig_loc,
11281 self.buf.as_ptr().wrapping_add(pos) as usize,
11282 )))
11283 }
11284}
11285impl std::fmt::Debug for IterableOpNapiGetDoReply<'_> {
11286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11287 let mut fmt = f.debug_struct("OpNapiGetDoReply");
11288 for attr in self.clone() {
11289 let attr = match attr {
11290 Ok(a) => a,
11291 Err(err) => {
11292 fmt.finish()?;
11293 f.write_str("Err(")?;
11294 err.fmt(f)?;
11295 return f.write_str(")");
11296 }
11297 };
11298 match attr {
11299 OpNapiGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
11300 OpNapiGetDoReply::Id(val) => fmt.field("Id", &val),
11301 OpNapiGetDoReply::Irq(val) => fmt.field("Irq", &val),
11302 OpNapiGetDoReply::Pid(val) => fmt.field("Pid", &val),
11303 OpNapiGetDoReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
11304 OpNapiGetDoReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
11305 OpNapiGetDoReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
11306 OpNapiGetDoReply::Threaded(val) => fmt.field(
11307 "Threaded",
11308 &FormatEnum(val.into(), NapiThreaded::from_value),
11309 ),
11310 };
11311 }
11312 fmt.finish()
11313 }
11314}
11315impl IterableOpNapiGetDoReply<'_> {
11316 pub fn lookup_attr(
11317 &self,
11318 offset: usize,
11319 missing_type: Option<u16>,
11320 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11321 let mut stack = Vec::new();
11322 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11323 if cur == offset + PushBuiltinNfgenmsg::len() {
11324 stack.push(("OpNapiGetDoReply", offset));
11325 return (
11326 stack,
11327 missing_type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11328 );
11329 }
11330 if cur > offset || cur + self.buf.len() < offset {
11331 return (stack, None);
11332 }
11333 let mut attrs = self.clone();
11334 let mut last_off = cur + attrs.pos;
11335 while let Some(attr) = attrs.next() {
11336 let Ok(attr) = attr else { break };
11337 match attr {
11338 OpNapiGetDoReply::Ifindex(val) => {
11339 if last_off == offset {
11340 stack.push(("Ifindex", last_off));
11341 break;
11342 }
11343 }
11344 OpNapiGetDoReply::Id(val) => {
11345 if last_off == offset {
11346 stack.push(("Id", last_off));
11347 break;
11348 }
11349 }
11350 OpNapiGetDoReply::Irq(val) => {
11351 if last_off == offset {
11352 stack.push(("Irq", last_off));
11353 break;
11354 }
11355 }
11356 OpNapiGetDoReply::Pid(val) => {
11357 if last_off == offset {
11358 stack.push(("Pid", last_off));
11359 break;
11360 }
11361 }
11362 OpNapiGetDoReply::DeferHardIrqs(val) => {
11363 if last_off == offset {
11364 stack.push(("DeferHardIrqs", last_off));
11365 break;
11366 }
11367 }
11368 OpNapiGetDoReply::GroFlushTimeout(val) => {
11369 if last_off == offset {
11370 stack.push(("GroFlushTimeout", last_off));
11371 break;
11372 }
11373 }
11374 OpNapiGetDoReply::IrqSuspendTimeout(val) => {
11375 if last_off == offset {
11376 stack.push(("IrqSuspendTimeout", last_off));
11377 break;
11378 }
11379 }
11380 OpNapiGetDoReply::Threaded(val) => {
11381 if last_off == offset {
11382 stack.push(("Threaded", last_off));
11383 break;
11384 }
11385 }
11386 _ => {}
11387 };
11388 last_off = cur + attrs.pos;
11389 }
11390 if !stack.is_empty() {
11391 stack.push(("OpNapiGetDoReply", cur));
11392 }
11393 (stack, None)
11394 }
11395}
11396#[derive(Debug)]
11397pub struct RequestOpNapiGetDoRequest<'r> {
11398 request: Request<'r>,
11399}
11400impl<'r> RequestOpNapiGetDoRequest<'r> {
11401 pub fn new(mut request: Request<'r>) -> Self {
11402 PushOpNapiGetDoRequest::write_header(&mut request.buf_mut());
11403 Self { request: request }
11404 }
11405 pub fn encode(&mut self) -> PushOpNapiGetDoRequest<&mut Vec<u8>> {
11406 PushOpNapiGetDoRequest::new_without_header(self.request.buf_mut())
11407 }
11408 pub fn into_encoder(self) -> PushOpNapiGetDoRequest<RequestBuf<'r>> {
11409 PushOpNapiGetDoRequest::new_without_header(self.request.buf)
11410 }
11411 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiGetDoRequest<'buf> {
11412 OpNapiGetDoRequest::new(buf)
11413 }
11414}
11415impl NetlinkRequest for RequestOpNapiGetDoRequest<'_> {
11416 fn protocol(&self) -> Protocol {
11417 Protocol::Generic("netdev".as_bytes())
11418 }
11419 fn flags(&self) -> u16 {
11420 self.request.flags
11421 }
11422 fn payload(&self) -> &[u8] {
11423 self.request.buf()
11424 }
11425 type ReplyType<'buf> = IterableOpNapiGetDoReply<'buf>;
11426 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
11427 OpNapiGetDoReply::new(buf)
11428 }
11429 fn lookup(
11430 buf: &[u8],
11431 offset: usize,
11432 missing_type: Option<u16>,
11433 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11434 OpNapiGetDoRequest::new(buf).lookup_attr(offset, missing_type)
11435 }
11436}
11437#[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n"]
11438pub struct PushOpQstatsGetDumpRequest<Prev: Rec> {
11439 pub(crate) prev: Option<Prev>,
11440 pub(crate) header_offset: Option<usize>,
11441}
11442impl<Prev: Rec> Rec for PushOpQstatsGetDumpRequest<Prev> {
11443 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11444 self.prev.as_mut().unwrap().as_rec_mut()
11445 }
11446 fn as_rec(&self) -> &Vec<u8> {
11447 self.prev.as_ref().unwrap().as_rec()
11448 }
11449}
11450impl<Prev: Rec> PushOpQstatsGetDumpRequest<Prev> {
11451 pub fn new(mut prev: Prev) -> Self {
11452 Self::write_header(&mut prev);
11453 Self::new_without_header(prev)
11454 }
11455 fn new_without_header(prev: Prev) -> Self {
11456 Self {
11457 prev: Some(prev),
11458 header_offset: None,
11459 }
11460 }
11461 fn write_header(prev: &mut Prev) {
11462 let mut header = PushBuiltinNfgenmsg::new();
11463 header.set_cmd(12u8);
11464 header.set_version(1u8);
11465 prev.as_rec_mut().extend(header.as_slice());
11466 }
11467 pub fn end_nested(mut self) -> Prev {
11468 let mut prev = self.prev.take().unwrap();
11469 if let Some(header_offset) = &self.header_offset {
11470 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11471 }
11472 prev
11473 }
11474 #[doc = "ifindex of the netdevice to which stats belong."]
11475 pub fn push_ifindex(mut self, value: u32) -> Self {
11476 push_header(self.as_rec_mut(), 1u16, 4 as u16);
11477 self.as_rec_mut().extend(value.to_ne_bytes());
11478 self
11479 }
11480 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11481 pub fn push_scope(mut self, value: u32) -> Self {
11482 push_header(self.as_rec_mut(), 4u16, 4 as u16);
11483 self.as_rec_mut().extend(value.to_ne_bytes());
11484 self
11485 }
11486}
11487impl<Prev: Rec> Drop for PushOpQstatsGetDumpRequest<Prev> {
11488 fn drop(&mut self) {
11489 if let Some(prev) = &mut self.prev {
11490 if let Some(header_offset) = &self.header_offset {
11491 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11492 }
11493 }
11494 }
11495}
11496#[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n"]
11497#[derive(Clone)]
11498pub enum OpQstatsGetDumpRequest {
11499 #[doc = "ifindex of the netdevice to which stats belong."]
11500 Ifindex(u32),
11501 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11502 Scope(u32),
11503}
11504impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11505 #[doc = "ifindex of the netdevice to which stats belong."]
11506 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11507 let mut iter = self.clone();
11508 iter.pos = 0;
11509 for attr in iter {
11510 if let OpQstatsGetDumpRequest::Ifindex(val) = attr? {
11511 return Ok(val);
11512 }
11513 }
11514 Err(ErrorContext::new_missing(
11515 "OpQstatsGetDumpRequest",
11516 "Ifindex",
11517 self.orig_loc,
11518 self.buf.as_ptr() as usize,
11519 ))
11520 }
11521 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11522 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
11523 let mut iter = self.clone();
11524 iter.pos = 0;
11525 for attr in iter {
11526 if let OpQstatsGetDumpRequest::Scope(val) = attr? {
11527 return Ok(val);
11528 }
11529 }
11530 Err(ErrorContext::new_missing(
11531 "OpQstatsGetDumpRequest",
11532 "Scope",
11533 self.orig_loc,
11534 self.buf.as_ptr() as usize,
11535 ))
11536 }
11537}
11538impl OpQstatsGetDumpRequest {
11539 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpRequest<'a> {
11540 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11541 IterableOpQstatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
11542 }
11543 fn attr_from_type(r#type: u16) -> Option<&'static str> {
11544 Qstats::attr_from_type(r#type)
11545 }
11546}
11547#[derive(Clone, Copy, Default)]
11548pub struct IterableOpQstatsGetDumpRequest<'a> {
11549 buf: &'a [u8],
11550 pos: usize,
11551 orig_loc: usize,
11552}
11553impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11554 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11555 Self {
11556 buf,
11557 pos: 0,
11558 orig_loc,
11559 }
11560 }
11561 pub fn get_buf(&self) -> &'a [u8] {
11562 self.buf
11563 }
11564}
11565impl<'a> Iterator for IterableOpQstatsGetDumpRequest<'a> {
11566 type Item = Result<OpQstatsGetDumpRequest, ErrorContext>;
11567 fn next(&mut self) -> Option<Self::Item> {
11568 let pos = self.pos;
11569 let mut r#type;
11570 loop {
11571 r#type = None;
11572 if self.buf.len() == self.pos {
11573 return None;
11574 }
11575 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
11576 break;
11577 };
11578 r#type = Some(header.r#type);
11579 let res = match header.r#type {
11580 1u16 => OpQstatsGetDumpRequest::Ifindex({
11581 let res = parse_u32(next);
11582 let Some(val) = res else { break };
11583 val
11584 }),
11585 4u16 => OpQstatsGetDumpRequest::Scope({
11586 let res = parse_u32(next);
11587 let Some(val) = res else { break };
11588 val
11589 }),
11590 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
11591 n => continue,
11592 };
11593 return Some(Ok(res));
11594 }
11595 Some(Err(ErrorContext::new(
11596 "OpQstatsGetDumpRequest",
11597 r#type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11598 self.orig_loc,
11599 self.buf.as_ptr().wrapping_add(pos) as usize,
11600 )))
11601 }
11602}
11603impl std::fmt::Debug for IterableOpQstatsGetDumpRequest<'_> {
11604 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11605 let mut fmt = f.debug_struct("OpQstatsGetDumpRequest");
11606 for attr in self.clone() {
11607 let attr = match attr {
11608 Ok(a) => a,
11609 Err(err) => {
11610 fmt.finish()?;
11611 f.write_str("Err(")?;
11612 err.fmt(f)?;
11613 return f.write_str(")");
11614 }
11615 };
11616 match attr {
11617 OpQstatsGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
11618 OpQstatsGetDumpRequest::Scope(val) => {
11619 fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
11620 }
11621 };
11622 }
11623 fmt.finish()
11624 }
11625}
11626impl IterableOpQstatsGetDumpRequest<'_> {
11627 pub fn lookup_attr(
11628 &self,
11629 offset: usize,
11630 missing_type: Option<u16>,
11631 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11632 let mut stack = Vec::new();
11633 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11634 if cur == offset + PushBuiltinNfgenmsg::len() {
11635 stack.push(("OpQstatsGetDumpRequest", offset));
11636 return (
11637 stack,
11638 missing_type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11639 );
11640 }
11641 if cur > offset || cur + self.buf.len() < offset {
11642 return (stack, None);
11643 }
11644 let mut attrs = self.clone();
11645 let mut last_off = cur + attrs.pos;
11646 while let Some(attr) = attrs.next() {
11647 let Ok(attr) = attr else { break };
11648 match attr {
11649 OpQstatsGetDumpRequest::Ifindex(val) => {
11650 if last_off == offset {
11651 stack.push(("Ifindex", last_off));
11652 break;
11653 }
11654 }
11655 OpQstatsGetDumpRequest::Scope(val) => {
11656 if last_off == offset {
11657 stack.push(("Scope", last_off));
11658 break;
11659 }
11660 }
11661 _ => {}
11662 };
11663 last_off = cur + attrs.pos;
11664 }
11665 if !stack.is_empty() {
11666 stack.push(("OpQstatsGetDumpRequest", cur));
11667 }
11668 (stack, None)
11669 }
11670}
11671#[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n"]
11672pub struct PushOpQstatsGetDumpReply<Prev: Rec> {
11673 pub(crate) prev: Option<Prev>,
11674 pub(crate) header_offset: Option<usize>,
11675}
11676impl<Prev: Rec> Rec for PushOpQstatsGetDumpReply<Prev> {
11677 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11678 self.prev.as_mut().unwrap().as_rec_mut()
11679 }
11680 fn as_rec(&self) -> &Vec<u8> {
11681 self.prev.as_ref().unwrap().as_rec()
11682 }
11683}
11684impl<Prev: Rec> PushOpQstatsGetDumpReply<Prev> {
11685 pub fn new(mut prev: Prev) -> Self {
11686 Self::write_header(&mut prev);
11687 Self::new_without_header(prev)
11688 }
11689 fn new_without_header(prev: Prev) -> Self {
11690 Self {
11691 prev: Some(prev),
11692 header_offset: None,
11693 }
11694 }
11695 fn write_header(prev: &mut Prev) {
11696 let mut header = PushBuiltinNfgenmsg::new();
11697 header.set_cmd(12u8);
11698 header.set_version(1u8);
11699 prev.as_rec_mut().extend(header.as_slice());
11700 }
11701 pub fn end_nested(mut self) -> Prev {
11702 let mut prev = self.prev.take().unwrap();
11703 if let Some(header_offset) = &self.header_offset {
11704 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11705 }
11706 prev
11707 }
11708 #[doc = "ifindex of the netdevice to which stats belong."]
11709 pub fn push_ifindex(mut self, value: u32) -> Self {
11710 push_header(self.as_rec_mut(), 1u16, 4 as u16);
11711 self.as_rec_mut().extend(value.to_ne_bytes());
11712 self
11713 }
11714 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11715 pub fn push_queue_type(mut self, value: u32) -> Self {
11716 push_header(self.as_rec_mut(), 2u16, 4 as u16);
11717 self.as_rec_mut().extend(value.to_ne_bytes());
11718 self
11719 }
11720 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11721 pub fn push_queue_id(mut self, value: u32) -> Self {
11722 push_header(self.as_rec_mut(), 3u16, 4 as u16);
11723 self.as_rec_mut().extend(value.to_ne_bytes());
11724 self
11725 }
11726 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
11727 pub fn push_rx_packets(mut self, value: u32) -> Self {
11728 push_header(self.as_rec_mut(), 8u16, 4 as u16);
11729 self.as_rec_mut().extend(value.to_ne_bytes());
11730 self
11731 }
11732 #[doc = "Successfully received bytes, see `rx-packets`."]
11733 pub fn push_rx_bytes(mut self, value: u32) -> Self {
11734 push_header(self.as_rec_mut(), 9u16, 4 as u16);
11735 self.as_rec_mut().extend(value.to_ne_bytes());
11736 self
11737 }
11738 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
11739 pub fn push_tx_packets(mut self, value: u32) -> Self {
11740 push_header(self.as_rec_mut(), 10u16, 4 as u16);
11741 self.as_rec_mut().extend(value.to_ne_bytes());
11742 self
11743 }
11744 #[doc = "Successfully sent bytes, see `tx-packets`."]
11745 pub fn push_tx_bytes(mut self, value: u32) -> Self {
11746 push_header(self.as_rec_mut(), 11u16, 4 as u16);
11747 self.as_rec_mut().extend(value.to_ne_bytes());
11748 self
11749 }
11750 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
11751 pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
11752 push_header(self.as_rec_mut(), 12u16, 4 as u16);
11753 self.as_rec_mut().extend(value.to_ne_bytes());
11754 self
11755 }
11756 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
11757 pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
11758 push_header(self.as_rec_mut(), 13u16, 4 as u16);
11759 self.as_rec_mut().extend(value.to_ne_bytes());
11760 self
11761 }
11762 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11763 pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
11764 push_header(self.as_rec_mut(), 14u16, 4 as u16);
11765 self.as_rec_mut().extend(value.to_ne_bytes());
11766 self
11767 }
11768 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11769 pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
11770 push_header(self.as_rec_mut(), 15u16, 4 as u16);
11771 self.as_rec_mut().extend(value.to_ne_bytes());
11772 self
11773 }
11774 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11775 pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
11776 push_header(self.as_rec_mut(), 16u16, 4 as u16);
11777 self.as_rec_mut().extend(value.to_ne_bytes());
11778 self
11779 }
11780 #[doc = "Number of packets that were not checksummed by device."]
11781 pub fn push_rx_csum_none(mut self, value: u32) -> Self {
11782 push_header(self.as_rec_mut(), 17u16, 4 as u16);
11783 self.as_rec_mut().extend(value.to_ne_bytes());
11784 self
11785 }
11786 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11787 pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
11788 push_header(self.as_rec_mut(), 18u16, 4 as u16);
11789 self.as_rec_mut().extend(value.to_ne_bytes());
11790 self
11791 }
11792 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
11793 pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
11794 push_header(self.as_rec_mut(), 19u16, 4 as u16);
11795 self.as_rec_mut().extend(value.to_ne_bytes());
11796 self
11797 }
11798 #[doc = "See `rx-hw-gro-packets`."]
11799 pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
11800 push_header(self.as_rec_mut(), 20u16, 4 as u16);
11801 self.as_rec_mut().extend(value.to_ne_bytes());
11802 self
11803 }
11804 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11805 pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
11806 push_header(self.as_rec_mut(), 21u16, 4 as u16);
11807 self.as_rec_mut().extend(value.to_ne_bytes());
11808 self
11809 }
11810 #[doc = "See `rx-hw-gro-wire-packets`."]
11811 pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
11812 push_header(self.as_rec_mut(), 22u16, 4 as u16);
11813 self.as_rec_mut().extend(value.to_ne_bytes());
11814 self
11815 }
11816 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11817 pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11818 push_header(self.as_rec_mut(), 23u16, 4 as u16);
11819 self.as_rec_mut().extend(value.to_ne_bytes());
11820 self
11821 }
11822 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
11823 pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
11824 push_header(self.as_rec_mut(), 24u16, 4 as u16);
11825 self.as_rec_mut().extend(value.to_ne_bytes());
11826 self
11827 }
11828 #[doc = "Number of packets dropped because they were invalid or malformed."]
11829 pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
11830 push_header(self.as_rec_mut(), 25u16, 4 as u16);
11831 self.as_rec_mut().extend(value.to_ne_bytes());
11832 self
11833 }
11834 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11835 pub fn push_tx_csum_none(mut self, value: u32) -> Self {
11836 push_header(self.as_rec_mut(), 26u16, 4 as u16);
11837 self.as_rec_mut().extend(value.to_ne_bytes());
11838 self
11839 }
11840 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
11841 pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
11842 push_header(self.as_rec_mut(), 27u16, 4 as u16);
11843 self.as_rec_mut().extend(value.to_ne_bytes());
11844 self
11845 }
11846 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11847 pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
11848 push_header(self.as_rec_mut(), 28u16, 4 as u16);
11849 self.as_rec_mut().extend(value.to_ne_bytes());
11850 self
11851 }
11852 #[doc = "See `tx-hw-gso-packets`."]
11853 pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
11854 push_header(self.as_rec_mut(), 29u16, 4 as u16);
11855 self.as_rec_mut().extend(value.to_ne_bytes());
11856 self
11857 }
11858 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11859 pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
11860 push_header(self.as_rec_mut(), 30u16, 4 as u16);
11861 self.as_rec_mut().extend(value.to_ne_bytes());
11862 self
11863 }
11864 #[doc = "See `tx-hw-gso-wire-packets`."]
11865 pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
11866 push_header(self.as_rec_mut(), 31u16, 4 as u16);
11867 self.as_rec_mut().extend(value.to_ne_bytes());
11868 self
11869 }
11870 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11871 pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11872 push_header(self.as_rec_mut(), 32u16, 4 as u16);
11873 self.as_rec_mut().extend(value.to_ne_bytes());
11874 self
11875 }
11876 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
11877 pub fn push_tx_stop(mut self, value: u32) -> Self {
11878 push_header(self.as_rec_mut(), 33u16, 4 as u16);
11879 self.as_rec_mut().extend(value.to_ne_bytes());
11880 self
11881 }
11882 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11883 pub fn push_tx_wake(mut self, value: u32) -> Self {
11884 push_header(self.as_rec_mut(), 34u16, 4 as u16);
11885 self.as_rec_mut().extend(value.to_ne_bytes());
11886 self
11887 }
11888}
11889impl<Prev: Rec> Drop for PushOpQstatsGetDumpReply<Prev> {
11890 fn drop(&mut self) {
11891 if let Some(prev) = &mut self.prev {
11892 if let Some(header_offset) = &self.header_offset {
11893 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11894 }
11895 }
11896 }
11897}
11898#[doc = "Get / dump fine grained statistics. Which statistics are reported\ndepends on the device and the driver, and whether the driver stores\nsoftware counters per-queue.\n"]
11899#[derive(Clone)]
11900pub enum OpQstatsGetDumpReply {
11901 #[doc = "ifindex of the netdevice to which stats belong."]
11902 Ifindex(u32),
11903 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11904 QueueType(u32),
11905 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11906 QueueId(u32),
11907 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
11908 RxPackets(u32),
11909 #[doc = "Successfully received bytes, see `rx-packets`."]
11910 RxBytes(u32),
11911 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
11912 TxPackets(u32),
11913 #[doc = "Successfully sent bytes, see `tx-packets`."]
11914 TxBytes(u32),
11915 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
11916 RxAllocFail(u32),
11917 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
11918 RxHwDrops(u32),
11919 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11920 RxHwDropOverruns(u32),
11921 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11922 RxCsumComplete(u32),
11923 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11924 RxCsumUnnecessary(u32),
11925 #[doc = "Number of packets that were not checksummed by device."]
11926 RxCsumNone(u32),
11927 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11928 RxCsumBad(u32),
11929 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
11930 RxHwGroPackets(u32),
11931 #[doc = "See `rx-hw-gro-packets`."]
11932 RxHwGroBytes(u32),
11933 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11934 RxHwGroWirePackets(u32),
11935 #[doc = "See `rx-hw-gro-wire-packets`."]
11936 RxHwGroWireBytes(u32),
11937 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11938 RxHwDropRatelimits(u32),
11939 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
11940 TxHwDrops(u32),
11941 #[doc = "Number of packets dropped because they were invalid or malformed."]
11942 TxHwDropErrors(u32),
11943 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11944 TxCsumNone(u32),
11945 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
11946 TxNeedsCsum(u32),
11947 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11948 TxHwGsoPackets(u32),
11949 #[doc = "See `tx-hw-gso-packets`."]
11950 TxHwGsoBytes(u32),
11951 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11952 TxHwGsoWirePackets(u32),
11953 #[doc = "See `tx-hw-gso-wire-packets`."]
11954 TxHwGsoWireBytes(u32),
11955 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11956 TxHwDropRatelimits(u32),
11957 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
11958 TxStop(u32),
11959 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11960 TxWake(u32),
11961}
11962impl<'a> IterableOpQstatsGetDumpReply<'a> {
11963 #[doc = "ifindex of the netdevice to which stats belong."]
11964 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11965 let mut iter = self.clone();
11966 iter.pos = 0;
11967 for attr in iter {
11968 if let OpQstatsGetDumpReply::Ifindex(val) = attr? {
11969 return Ok(val);
11970 }
11971 }
11972 Err(ErrorContext::new_missing(
11973 "OpQstatsGetDumpReply",
11974 "Ifindex",
11975 self.orig_loc,
11976 self.buf.as_ptr() as usize,
11977 ))
11978 }
11979 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11980 pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
11981 let mut iter = self.clone();
11982 iter.pos = 0;
11983 for attr in iter {
11984 if let OpQstatsGetDumpReply::QueueType(val) = attr? {
11985 return Ok(val);
11986 }
11987 }
11988 Err(ErrorContext::new_missing(
11989 "OpQstatsGetDumpReply",
11990 "QueueType",
11991 self.orig_loc,
11992 self.buf.as_ptr() as usize,
11993 ))
11994 }
11995 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11996 pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
11997 let mut iter = self.clone();
11998 iter.pos = 0;
11999 for attr in iter {
12000 if let OpQstatsGetDumpReply::QueueId(val) = attr? {
12001 return Ok(val);
12002 }
12003 }
12004 Err(ErrorContext::new_missing(
12005 "OpQstatsGetDumpReply",
12006 "QueueId",
12007 self.orig_loc,
12008 self.buf.as_ptr() as usize,
12009 ))
12010 }
12011 #[doc = "Number of wire packets successfully received and passed to the stack.\nFor drivers supporting XDP, XDP is considered the first layer\nof the stack, so packets consumed by XDP are still counted here.\n"]
12012 pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
12013 let mut iter = self.clone();
12014 iter.pos = 0;
12015 for attr in iter {
12016 if let OpQstatsGetDumpReply::RxPackets(val) = attr? {
12017 return Ok(val);
12018 }
12019 }
12020 Err(ErrorContext::new_missing(
12021 "OpQstatsGetDumpReply",
12022 "RxPackets",
12023 self.orig_loc,
12024 self.buf.as_ptr() as usize,
12025 ))
12026 }
12027 #[doc = "Successfully received bytes, see `rx-packets`."]
12028 pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
12029 let mut iter = self.clone();
12030 iter.pos = 0;
12031 for attr in iter {
12032 if let OpQstatsGetDumpReply::RxBytes(val) = attr? {
12033 return Ok(val);
12034 }
12035 }
12036 Err(ErrorContext::new_missing(
12037 "OpQstatsGetDumpReply",
12038 "RxBytes",
12039 self.orig_loc,
12040 self.buf.as_ptr() as usize,
12041 ))
12042 }
12043 #[doc = "Number of wire packets successfully sent. Packet is considered to be\nsuccessfully sent once it is in device memory (usually this means\nthe device has issued a DMA completion for the packet).\n"]
12044 pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
12045 let mut iter = self.clone();
12046 iter.pos = 0;
12047 for attr in iter {
12048 if let OpQstatsGetDumpReply::TxPackets(val) = attr? {
12049 return Ok(val);
12050 }
12051 }
12052 Err(ErrorContext::new_missing(
12053 "OpQstatsGetDumpReply",
12054 "TxPackets",
12055 self.orig_loc,
12056 self.buf.as_ptr() as usize,
12057 ))
12058 }
12059 #[doc = "Successfully sent bytes, see `tx-packets`."]
12060 pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
12061 let mut iter = self.clone();
12062 iter.pos = 0;
12063 for attr in iter {
12064 if let OpQstatsGetDumpReply::TxBytes(val) = attr? {
12065 return Ok(val);
12066 }
12067 }
12068 Err(ErrorContext::new_missing(
12069 "OpQstatsGetDumpReply",
12070 "TxBytes",
12071 self.orig_loc,
12072 self.buf.as_ptr() as usize,
12073 ))
12074 }
12075 #[doc = "Number of times skb or buffer allocation failed on the Rx datapath.\nAllocation failure may, or may not result in a packet drop, depending\non driver implementation and whether system recovers quickly.\n"]
12076 pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
12077 let mut iter = self.clone();
12078 iter.pos = 0;
12079 for attr in iter {
12080 if let OpQstatsGetDumpReply::RxAllocFail(val) = attr? {
12081 return Ok(val);
12082 }
12083 }
12084 Err(ErrorContext::new_missing(
12085 "OpQstatsGetDumpReply",
12086 "RxAllocFail",
12087 self.orig_loc,
12088 self.buf.as_ptr() as usize,
12089 ))
12090 }
12091 #[doc = "Number of all packets which entered the device, but never left it,\nincluding but not limited to: packets dropped due to lack of buffer\nspace, processing errors, explicit or implicit policies and packet\nfilters.\n"]
12092 pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
12093 let mut iter = self.clone();
12094 iter.pos = 0;
12095 for attr in iter {
12096 if let OpQstatsGetDumpReply::RxHwDrops(val) = attr? {
12097 return Ok(val);
12098 }
12099 }
12100 Err(ErrorContext::new_missing(
12101 "OpQstatsGetDumpReply",
12102 "RxHwDrops",
12103 self.orig_loc,
12104 self.buf.as_ptr() as usize,
12105 ))
12106 }
12107 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
12108 pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
12109 let mut iter = self.clone();
12110 iter.pos = 0;
12111 for attr in iter {
12112 if let OpQstatsGetDumpReply::RxHwDropOverruns(val) = attr? {
12113 return Ok(val);
12114 }
12115 }
12116 Err(ErrorContext::new_missing(
12117 "OpQstatsGetDumpReply",
12118 "RxHwDropOverruns",
12119 self.orig_loc,
12120 self.buf.as_ptr() as usize,
12121 ))
12122 }
12123 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
12124 pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
12125 let mut iter = self.clone();
12126 iter.pos = 0;
12127 for attr in iter {
12128 if let OpQstatsGetDumpReply::RxCsumComplete(val) = attr? {
12129 return Ok(val);
12130 }
12131 }
12132 Err(ErrorContext::new_missing(
12133 "OpQstatsGetDumpReply",
12134 "RxCsumComplete",
12135 self.orig_loc,
12136 self.buf.as_ptr() as usize,
12137 ))
12138 }
12139 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
12140 pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
12141 let mut iter = self.clone();
12142 iter.pos = 0;
12143 for attr in iter {
12144 if let OpQstatsGetDumpReply::RxCsumUnnecessary(val) = attr? {
12145 return Ok(val);
12146 }
12147 }
12148 Err(ErrorContext::new_missing(
12149 "OpQstatsGetDumpReply",
12150 "RxCsumUnnecessary",
12151 self.orig_loc,
12152 self.buf.as_ptr() as usize,
12153 ))
12154 }
12155 #[doc = "Number of packets that were not checksummed by device."]
12156 pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
12157 let mut iter = self.clone();
12158 iter.pos = 0;
12159 for attr in iter {
12160 if let OpQstatsGetDumpReply::RxCsumNone(val) = attr? {
12161 return Ok(val);
12162 }
12163 }
12164 Err(ErrorContext::new_missing(
12165 "OpQstatsGetDumpReply",
12166 "RxCsumNone",
12167 self.orig_loc,
12168 self.buf.as_ptr() as usize,
12169 ))
12170 }
12171 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
12172 pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
12173 let mut iter = self.clone();
12174 iter.pos = 0;
12175 for attr in iter {
12176 if let OpQstatsGetDumpReply::RxCsumBad(val) = attr? {
12177 return Ok(val);
12178 }
12179 }
12180 Err(ErrorContext::new_missing(
12181 "OpQstatsGetDumpReply",
12182 "RxCsumBad",
12183 self.orig_loc,
12184 self.buf.as_ptr() as usize,
12185 ))
12186 }
12187 #[doc = "Number of packets that were coalesced from smaller packets by the\ndevice. Counts only packets coalesced with the HW-GRO netdevice\nfeature, LRO-coalesced packets are not counted.\n"]
12188 pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
12189 let mut iter = self.clone();
12190 iter.pos = 0;
12191 for attr in iter {
12192 if let OpQstatsGetDumpReply::RxHwGroPackets(val) = attr? {
12193 return Ok(val);
12194 }
12195 }
12196 Err(ErrorContext::new_missing(
12197 "OpQstatsGetDumpReply",
12198 "RxHwGroPackets",
12199 self.orig_loc,
12200 self.buf.as_ptr() as usize,
12201 ))
12202 }
12203 #[doc = "See `rx-hw-gro-packets`."]
12204 pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
12205 let mut iter = self.clone();
12206 iter.pos = 0;
12207 for attr in iter {
12208 if let OpQstatsGetDumpReply::RxHwGroBytes(val) = attr? {
12209 return Ok(val);
12210 }
12211 }
12212 Err(ErrorContext::new_missing(
12213 "OpQstatsGetDumpReply",
12214 "RxHwGroBytes",
12215 self.orig_loc,
12216 self.buf.as_ptr() as usize,
12217 ))
12218 }
12219 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
12220 pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
12221 let mut iter = self.clone();
12222 iter.pos = 0;
12223 for attr in iter {
12224 if let OpQstatsGetDumpReply::RxHwGroWirePackets(val) = attr? {
12225 return Ok(val);
12226 }
12227 }
12228 Err(ErrorContext::new_missing(
12229 "OpQstatsGetDumpReply",
12230 "RxHwGroWirePackets",
12231 self.orig_loc,
12232 self.buf.as_ptr() as usize,
12233 ))
12234 }
12235 #[doc = "See `rx-hw-gro-wire-packets`."]
12236 pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
12237 let mut iter = self.clone();
12238 iter.pos = 0;
12239 for attr in iter {
12240 if let OpQstatsGetDumpReply::RxHwGroWireBytes(val) = attr? {
12241 return Ok(val);
12242 }
12243 }
12244 Err(ErrorContext::new_missing(
12245 "OpQstatsGetDumpReply",
12246 "RxHwGroWireBytes",
12247 self.orig_loc,
12248 self.buf.as_ptr() as usize,
12249 ))
12250 }
12251 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
12252 pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12253 let mut iter = self.clone();
12254 iter.pos = 0;
12255 for attr in iter {
12256 if let OpQstatsGetDumpReply::RxHwDropRatelimits(val) = attr? {
12257 return Ok(val);
12258 }
12259 }
12260 Err(ErrorContext::new_missing(
12261 "OpQstatsGetDumpReply",
12262 "RxHwDropRatelimits",
12263 self.orig_loc,
12264 self.buf.as_ptr() as usize,
12265 ))
12266 }
12267 #[doc = "Number of packets that arrived at the device but never left it,\nencompassing packets dropped for reasons such as processing errors, as\nwell as those affected by explicitly defined policies and packet\nfiltering criteria.\n"]
12268 pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
12269 let mut iter = self.clone();
12270 iter.pos = 0;
12271 for attr in iter {
12272 if let OpQstatsGetDumpReply::TxHwDrops(val) = attr? {
12273 return Ok(val);
12274 }
12275 }
12276 Err(ErrorContext::new_missing(
12277 "OpQstatsGetDumpReply",
12278 "TxHwDrops",
12279 self.orig_loc,
12280 self.buf.as_ptr() as usize,
12281 ))
12282 }
12283 #[doc = "Number of packets dropped because they were invalid or malformed."]
12284 pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
12285 let mut iter = self.clone();
12286 iter.pos = 0;
12287 for attr in iter {
12288 if let OpQstatsGetDumpReply::TxHwDropErrors(val) = attr? {
12289 return Ok(val);
12290 }
12291 }
12292 Err(ErrorContext::new_missing(
12293 "OpQstatsGetDumpReply",
12294 "TxHwDropErrors",
12295 self.orig_loc,
12296 self.buf.as_ptr() as usize,
12297 ))
12298 }
12299 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
12300 pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
12301 let mut iter = self.clone();
12302 iter.pos = 0;
12303 for attr in iter {
12304 if let OpQstatsGetDumpReply::TxCsumNone(val) = attr? {
12305 return Ok(val);
12306 }
12307 }
12308 Err(ErrorContext::new_missing(
12309 "OpQstatsGetDumpReply",
12310 "TxCsumNone",
12311 self.orig_loc,
12312 self.buf.as_ptr() as usize,
12313 ))
12314 }
12315 #[doc = "Number of packets that required the device to calculate the checksum.\nThis counter includes the number of GSO wire packets for which device\ncalculated the L4 checksum.\n"]
12316 pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
12317 let mut iter = self.clone();
12318 iter.pos = 0;
12319 for attr in iter {
12320 if let OpQstatsGetDumpReply::TxNeedsCsum(val) = attr? {
12321 return Ok(val);
12322 }
12323 }
12324 Err(ErrorContext::new_missing(
12325 "OpQstatsGetDumpReply",
12326 "TxNeedsCsum",
12327 self.orig_loc,
12328 self.buf.as_ptr() as usize,
12329 ))
12330 }
12331 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
12332 pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
12333 let mut iter = self.clone();
12334 iter.pos = 0;
12335 for attr in iter {
12336 if let OpQstatsGetDumpReply::TxHwGsoPackets(val) = attr? {
12337 return Ok(val);
12338 }
12339 }
12340 Err(ErrorContext::new_missing(
12341 "OpQstatsGetDumpReply",
12342 "TxHwGsoPackets",
12343 self.orig_loc,
12344 self.buf.as_ptr() as usize,
12345 ))
12346 }
12347 #[doc = "See `tx-hw-gso-packets`."]
12348 pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
12349 let mut iter = self.clone();
12350 iter.pos = 0;
12351 for attr in iter {
12352 if let OpQstatsGetDumpReply::TxHwGsoBytes(val) = attr? {
12353 return Ok(val);
12354 }
12355 }
12356 Err(ErrorContext::new_missing(
12357 "OpQstatsGetDumpReply",
12358 "TxHwGsoBytes",
12359 self.orig_loc,
12360 self.buf.as_ptr() as usize,
12361 ))
12362 }
12363 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
12364 pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
12365 let mut iter = self.clone();
12366 iter.pos = 0;
12367 for attr in iter {
12368 if let OpQstatsGetDumpReply::TxHwGsoWirePackets(val) = attr? {
12369 return Ok(val);
12370 }
12371 }
12372 Err(ErrorContext::new_missing(
12373 "OpQstatsGetDumpReply",
12374 "TxHwGsoWirePackets",
12375 self.orig_loc,
12376 self.buf.as_ptr() as usize,
12377 ))
12378 }
12379 #[doc = "See `tx-hw-gso-wire-packets`."]
12380 pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
12381 let mut iter = self.clone();
12382 iter.pos = 0;
12383 for attr in iter {
12384 if let OpQstatsGetDumpReply::TxHwGsoWireBytes(val) = attr? {
12385 return Ok(val);
12386 }
12387 }
12388 Err(ErrorContext::new_missing(
12389 "OpQstatsGetDumpReply",
12390 "TxHwGsoWireBytes",
12391 self.orig_loc,
12392 self.buf.as_ptr() as usize,
12393 ))
12394 }
12395 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
12396 pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12397 let mut iter = self.clone();
12398 iter.pos = 0;
12399 for attr in iter {
12400 if let OpQstatsGetDumpReply::TxHwDropRatelimits(val) = attr? {
12401 return Ok(val);
12402 }
12403 }
12404 Err(ErrorContext::new_missing(
12405 "OpQstatsGetDumpReply",
12406 "TxHwDropRatelimits",
12407 self.orig_loc,
12408 self.buf.as_ptr() as usize,
12409 ))
12410 }
12411 #[doc = "Number of times driver paused accepting new tx packets\nfrom the stack to this queue, because the queue was full.\nNote that if BQL is supported and enabled on the device\nthe networking stack will avoid queuing a lot of data at once.\n"]
12412 pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
12413 let mut iter = self.clone();
12414 iter.pos = 0;
12415 for attr in iter {
12416 if let OpQstatsGetDumpReply::TxStop(val) = attr? {
12417 return Ok(val);
12418 }
12419 }
12420 Err(ErrorContext::new_missing(
12421 "OpQstatsGetDumpReply",
12422 "TxStop",
12423 self.orig_loc,
12424 self.buf.as_ptr() as usize,
12425 ))
12426 }
12427 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
12428 pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
12429 let mut iter = self.clone();
12430 iter.pos = 0;
12431 for attr in iter {
12432 if let OpQstatsGetDumpReply::TxWake(val) = attr? {
12433 return Ok(val);
12434 }
12435 }
12436 Err(ErrorContext::new_missing(
12437 "OpQstatsGetDumpReply",
12438 "TxWake",
12439 self.orig_loc,
12440 self.buf.as_ptr() as usize,
12441 ))
12442 }
12443}
12444impl OpQstatsGetDumpReply {
12445 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpReply<'a> {
12446 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12447 IterableOpQstatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
12448 }
12449 fn attr_from_type(r#type: u16) -> Option<&'static str> {
12450 Qstats::attr_from_type(r#type)
12451 }
12452}
12453#[derive(Clone, Copy, Default)]
12454pub struct IterableOpQstatsGetDumpReply<'a> {
12455 buf: &'a [u8],
12456 pos: usize,
12457 orig_loc: usize,
12458}
12459impl<'a> IterableOpQstatsGetDumpReply<'a> {
12460 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
12461 Self {
12462 buf,
12463 pos: 0,
12464 orig_loc,
12465 }
12466 }
12467 pub fn get_buf(&self) -> &'a [u8] {
12468 self.buf
12469 }
12470}
12471impl<'a> Iterator for IterableOpQstatsGetDumpReply<'a> {
12472 type Item = Result<OpQstatsGetDumpReply, ErrorContext>;
12473 fn next(&mut self) -> Option<Self::Item> {
12474 let pos = self.pos;
12475 let mut r#type;
12476 loop {
12477 r#type = None;
12478 if self.buf.len() == self.pos {
12479 return None;
12480 }
12481 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
12482 break;
12483 };
12484 r#type = Some(header.r#type);
12485 let res = match header.r#type {
12486 1u16 => OpQstatsGetDumpReply::Ifindex({
12487 let res = parse_u32(next);
12488 let Some(val) = res else { break };
12489 val
12490 }),
12491 2u16 => OpQstatsGetDumpReply::QueueType({
12492 let res = parse_u32(next);
12493 let Some(val) = res else { break };
12494 val
12495 }),
12496 3u16 => OpQstatsGetDumpReply::QueueId({
12497 let res = parse_u32(next);
12498 let Some(val) = res else { break };
12499 val
12500 }),
12501 8u16 => OpQstatsGetDumpReply::RxPackets({
12502 let res = parse_u32(next);
12503 let Some(val) = res else { break };
12504 val
12505 }),
12506 9u16 => OpQstatsGetDumpReply::RxBytes({
12507 let res = parse_u32(next);
12508 let Some(val) = res else { break };
12509 val
12510 }),
12511 10u16 => OpQstatsGetDumpReply::TxPackets({
12512 let res = parse_u32(next);
12513 let Some(val) = res else { break };
12514 val
12515 }),
12516 11u16 => OpQstatsGetDumpReply::TxBytes({
12517 let res = parse_u32(next);
12518 let Some(val) = res else { break };
12519 val
12520 }),
12521 12u16 => OpQstatsGetDumpReply::RxAllocFail({
12522 let res = parse_u32(next);
12523 let Some(val) = res else { break };
12524 val
12525 }),
12526 13u16 => OpQstatsGetDumpReply::RxHwDrops({
12527 let res = parse_u32(next);
12528 let Some(val) = res else { break };
12529 val
12530 }),
12531 14u16 => OpQstatsGetDumpReply::RxHwDropOverruns({
12532 let res = parse_u32(next);
12533 let Some(val) = res else { break };
12534 val
12535 }),
12536 15u16 => OpQstatsGetDumpReply::RxCsumComplete({
12537 let res = parse_u32(next);
12538 let Some(val) = res else { break };
12539 val
12540 }),
12541 16u16 => OpQstatsGetDumpReply::RxCsumUnnecessary({
12542 let res = parse_u32(next);
12543 let Some(val) = res else { break };
12544 val
12545 }),
12546 17u16 => OpQstatsGetDumpReply::RxCsumNone({
12547 let res = parse_u32(next);
12548 let Some(val) = res else { break };
12549 val
12550 }),
12551 18u16 => OpQstatsGetDumpReply::RxCsumBad({
12552 let res = parse_u32(next);
12553 let Some(val) = res else { break };
12554 val
12555 }),
12556 19u16 => OpQstatsGetDumpReply::RxHwGroPackets({
12557 let res = parse_u32(next);
12558 let Some(val) = res else { break };
12559 val
12560 }),
12561 20u16 => OpQstatsGetDumpReply::RxHwGroBytes({
12562 let res = parse_u32(next);
12563 let Some(val) = res else { break };
12564 val
12565 }),
12566 21u16 => OpQstatsGetDumpReply::RxHwGroWirePackets({
12567 let res = parse_u32(next);
12568 let Some(val) = res else { break };
12569 val
12570 }),
12571 22u16 => OpQstatsGetDumpReply::RxHwGroWireBytes({
12572 let res = parse_u32(next);
12573 let Some(val) = res else { break };
12574 val
12575 }),
12576 23u16 => OpQstatsGetDumpReply::RxHwDropRatelimits({
12577 let res = parse_u32(next);
12578 let Some(val) = res else { break };
12579 val
12580 }),
12581 24u16 => OpQstatsGetDumpReply::TxHwDrops({
12582 let res = parse_u32(next);
12583 let Some(val) = res else { break };
12584 val
12585 }),
12586 25u16 => OpQstatsGetDumpReply::TxHwDropErrors({
12587 let res = parse_u32(next);
12588 let Some(val) = res else { break };
12589 val
12590 }),
12591 26u16 => OpQstatsGetDumpReply::TxCsumNone({
12592 let res = parse_u32(next);
12593 let Some(val) = res else { break };
12594 val
12595 }),
12596 27u16 => OpQstatsGetDumpReply::TxNeedsCsum({
12597 let res = parse_u32(next);
12598 let Some(val) = res else { break };
12599 val
12600 }),
12601 28u16 => OpQstatsGetDumpReply::TxHwGsoPackets({
12602 let res = parse_u32(next);
12603 let Some(val) = res else { break };
12604 val
12605 }),
12606 29u16 => OpQstatsGetDumpReply::TxHwGsoBytes({
12607 let res = parse_u32(next);
12608 let Some(val) = res else { break };
12609 val
12610 }),
12611 30u16 => OpQstatsGetDumpReply::TxHwGsoWirePackets({
12612 let res = parse_u32(next);
12613 let Some(val) = res else { break };
12614 val
12615 }),
12616 31u16 => OpQstatsGetDumpReply::TxHwGsoWireBytes({
12617 let res = parse_u32(next);
12618 let Some(val) = res else { break };
12619 val
12620 }),
12621 32u16 => OpQstatsGetDumpReply::TxHwDropRatelimits({
12622 let res = parse_u32(next);
12623 let Some(val) = res else { break };
12624 val
12625 }),
12626 33u16 => OpQstatsGetDumpReply::TxStop({
12627 let res = parse_u32(next);
12628 let Some(val) = res else { break };
12629 val
12630 }),
12631 34u16 => OpQstatsGetDumpReply::TxWake({
12632 let res = parse_u32(next);
12633 let Some(val) = res else { break };
12634 val
12635 }),
12636 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
12637 n => continue,
12638 };
12639 return Some(Ok(res));
12640 }
12641 Some(Err(ErrorContext::new(
12642 "OpQstatsGetDumpReply",
12643 r#type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12644 self.orig_loc,
12645 self.buf.as_ptr().wrapping_add(pos) as usize,
12646 )))
12647 }
12648}
12649impl std::fmt::Debug for IterableOpQstatsGetDumpReply<'_> {
12650 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12651 let mut fmt = f.debug_struct("OpQstatsGetDumpReply");
12652 for attr in self.clone() {
12653 let attr = match attr {
12654 Ok(a) => a,
12655 Err(err) => {
12656 fmt.finish()?;
12657 f.write_str("Err(")?;
12658 err.fmt(f)?;
12659 return f.write_str(")");
12660 }
12661 };
12662 match attr {
12663 OpQstatsGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
12664 OpQstatsGetDumpReply::QueueType(val) => {
12665 fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
12666 }
12667 OpQstatsGetDumpReply::QueueId(val) => fmt.field("QueueId", &val),
12668 OpQstatsGetDumpReply::RxPackets(val) => fmt.field("RxPackets", &val),
12669 OpQstatsGetDumpReply::RxBytes(val) => fmt.field("RxBytes", &val),
12670 OpQstatsGetDumpReply::TxPackets(val) => fmt.field("TxPackets", &val),
12671 OpQstatsGetDumpReply::TxBytes(val) => fmt.field("TxBytes", &val),
12672 OpQstatsGetDumpReply::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
12673 OpQstatsGetDumpReply::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
12674 OpQstatsGetDumpReply::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
12675 OpQstatsGetDumpReply::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
12676 OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12677 fmt.field("RxCsumUnnecessary", &val)
12678 }
12679 OpQstatsGetDumpReply::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
12680 OpQstatsGetDumpReply::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
12681 OpQstatsGetDumpReply::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
12682 OpQstatsGetDumpReply::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
12683 OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12684 fmt.field("RxHwGroWirePackets", &val)
12685 }
12686 OpQstatsGetDumpReply::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
12687 OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12688 fmt.field("RxHwDropRatelimits", &val)
12689 }
12690 OpQstatsGetDumpReply::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
12691 OpQstatsGetDumpReply::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
12692 OpQstatsGetDumpReply::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
12693 OpQstatsGetDumpReply::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
12694 OpQstatsGetDumpReply::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
12695 OpQstatsGetDumpReply::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
12696 OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12697 fmt.field("TxHwGsoWirePackets", &val)
12698 }
12699 OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
12700 OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12701 fmt.field("TxHwDropRatelimits", &val)
12702 }
12703 OpQstatsGetDumpReply::TxStop(val) => fmt.field("TxStop", &val),
12704 OpQstatsGetDumpReply::TxWake(val) => fmt.field("TxWake", &val),
12705 };
12706 }
12707 fmt.finish()
12708 }
12709}
12710impl IterableOpQstatsGetDumpReply<'_> {
12711 pub fn lookup_attr(
12712 &self,
12713 offset: usize,
12714 missing_type: Option<u16>,
12715 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12716 let mut stack = Vec::new();
12717 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
12718 if cur == offset + PushBuiltinNfgenmsg::len() {
12719 stack.push(("OpQstatsGetDumpReply", offset));
12720 return (
12721 stack,
12722 missing_type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12723 );
12724 }
12725 if cur > offset || cur + self.buf.len() < offset {
12726 return (stack, None);
12727 }
12728 let mut attrs = self.clone();
12729 let mut last_off = cur + attrs.pos;
12730 while let Some(attr) = attrs.next() {
12731 let Ok(attr) = attr else { break };
12732 match attr {
12733 OpQstatsGetDumpReply::Ifindex(val) => {
12734 if last_off == offset {
12735 stack.push(("Ifindex", last_off));
12736 break;
12737 }
12738 }
12739 OpQstatsGetDumpReply::QueueType(val) => {
12740 if last_off == offset {
12741 stack.push(("QueueType", last_off));
12742 break;
12743 }
12744 }
12745 OpQstatsGetDumpReply::QueueId(val) => {
12746 if last_off == offset {
12747 stack.push(("QueueId", last_off));
12748 break;
12749 }
12750 }
12751 OpQstatsGetDumpReply::RxPackets(val) => {
12752 if last_off == offset {
12753 stack.push(("RxPackets", last_off));
12754 break;
12755 }
12756 }
12757 OpQstatsGetDumpReply::RxBytes(val) => {
12758 if last_off == offset {
12759 stack.push(("RxBytes", last_off));
12760 break;
12761 }
12762 }
12763 OpQstatsGetDumpReply::TxPackets(val) => {
12764 if last_off == offset {
12765 stack.push(("TxPackets", last_off));
12766 break;
12767 }
12768 }
12769 OpQstatsGetDumpReply::TxBytes(val) => {
12770 if last_off == offset {
12771 stack.push(("TxBytes", last_off));
12772 break;
12773 }
12774 }
12775 OpQstatsGetDumpReply::RxAllocFail(val) => {
12776 if last_off == offset {
12777 stack.push(("RxAllocFail", last_off));
12778 break;
12779 }
12780 }
12781 OpQstatsGetDumpReply::RxHwDrops(val) => {
12782 if last_off == offset {
12783 stack.push(("RxHwDrops", last_off));
12784 break;
12785 }
12786 }
12787 OpQstatsGetDumpReply::RxHwDropOverruns(val) => {
12788 if last_off == offset {
12789 stack.push(("RxHwDropOverruns", last_off));
12790 break;
12791 }
12792 }
12793 OpQstatsGetDumpReply::RxCsumComplete(val) => {
12794 if last_off == offset {
12795 stack.push(("RxCsumComplete", last_off));
12796 break;
12797 }
12798 }
12799 OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12800 if last_off == offset {
12801 stack.push(("RxCsumUnnecessary", last_off));
12802 break;
12803 }
12804 }
12805 OpQstatsGetDumpReply::RxCsumNone(val) => {
12806 if last_off == offset {
12807 stack.push(("RxCsumNone", last_off));
12808 break;
12809 }
12810 }
12811 OpQstatsGetDumpReply::RxCsumBad(val) => {
12812 if last_off == offset {
12813 stack.push(("RxCsumBad", last_off));
12814 break;
12815 }
12816 }
12817 OpQstatsGetDumpReply::RxHwGroPackets(val) => {
12818 if last_off == offset {
12819 stack.push(("RxHwGroPackets", last_off));
12820 break;
12821 }
12822 }
12823 OpQstatsGetDumpReply::RxHwGroBytes(val) => {
12824 if last_off == offset {
12825 stack.push(("RxHwGroBytes", last_off));
12826 break;
12827 }
12828 }
12829 OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12830 if last_off == offset {
12831 stack.push(("RxHwGroWirePackets", last_off));
12832 break;
12833 }
12834 }
12835 OpQstatsGetDumpReply::RxHwGroWireBytes(val) => {
12836 if last_off == offset {
12837 stack.push(("RxHwGroWireBytes", last_off));
12838 break;
12839 }
12840 }
12841 OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12842 if last_off == offset {
12843 stack.push(("RxHwDropRatelimits", last_off));
12844 break;
12845 }
12846 }
12847 OpQstatsGetDumpReply::TxHwDrops(val) => {
12848 if last_off == offset {
12849 stack.push(("TxHwDrops", last_off));
12850 break;
12851 }
12852 }
12853 OpQstatsGetDumpReply::TxHwDropErrors(val) => {
12854 if last_off == offset {
12855 stack.push(("TxHwDropErrors", last_off));
12856 break;
12857 }
12858 }
12859 OpQstatsGetDumpReply::TxCsumNone(val) => {
12860 if last_off == offset {
12861 stack.push(("TxCsumNone", last_off));
12862 break;
12863 }
12864 }
12865 OpQstatsGetDumpReply::TxNeedsCsum(val) => {
12866 if last_off == offset {
12867 stack.push(("TxNeedsCsum", last_off));
12868 break;
12869 }
12870 }
12871 OpQstatsGetDumpReply::TxHwGsoPackets(val) => {
12872 if last_off == offset {
12873 stack.push(("TxHwGsoPackets", last_off));
12874 break;
12875 }
12876 }
12877 OpQstatsGetDumpReply::TxHwGsoBytes(val) => {
12878 if last_off == offset {
12879 stack.push(("TxHwGsoBytes", last_off));
12880 break;
12881 }
12882 }
12883 OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12884 if last_off == offset {
12885 stack.push(("TxHwGsoWirePackets", last_off));
12886 break;
12887 }
12888 }
12889 OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => {
12890 if last_off == offset {
12891 stack.push(("TxHwGsoWireBytes", last_off));
12892 break;
12893 }
12894 }
12895 OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12896 if last_off == offset {
12897 stack.push(("TxHwDropRatelimits", last_off));
12898 break;
12899 }
12900 }
12901 OpQstatsGetDumpReply::TxStop(val) => {
12902 if last_off == offset {
12903 stack.push(("TxStop", last_off));
12904 break;
12905 }
12906 }
12907 OpQstatsGetDumpReply::TxWake(val) => {
12908 if last_off == offset {
12909 stack.push(("TxWake", last_off));
12910 break;
12911 }
12912 }
12913 _ => {}
12914 };
12915 last_off = cur + attrs.pos;
12916 }
12917 if !stack.is_empty() {
12918 stack.push(("OpQstatsGetDumpReply", cur));
12919 }
12920 (stack, None)
12921 }
12922}
12923#[derive(Debug)]
12924pub struct RequestOpQstatsGetDumpRequest<'r> {
12925 request: Request<'r>,
12926}
12927impl<'r> RequestOpQstatsGetDumpRequest<'r> {
12928 pub fn new(mut request: Request<'r>) -> Self {
12929 PushOpQstatsGetDumpRequest::write_header(&mut request.buf_mut());
12930 Self {
12931 request: request.set_dump(),
12932 }
12933 }
12934 pub fn encode(&mut self) -> PushOpQstatsGetDumpRequest<&mut Vec<u8>> {
12935 PushOpQstatsGetDumpRequest::new_without_header(self.request.buf_mut())
12936 }
12937 pub fn into_encoder(self) -> PushOpQstatsGetDumpRequest<RequestBuf<'r>> {
12938 PushOpQstatsGetDumpRequest::new_without_header(self.request.buf)
12939 }
12940 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpQstatsGetDumpRequest<'buf> {
12941 OpQstatsGetDumpRequest::new(buf)
12942 }
12943}
12944impl NetlinkRequest for RequestOpQstatsGetDumpRequest<'_> {
12945 fn protocol(&self) -> Protocol {
12946 Protocol::Generic("netdev".as_bytes())
12947 }
12948 fn flags(&self) -> u16 {
12949 self.request.flags
12950 }
12951 fn payload(&self) -> &[u8] {
12952 self.request.buf()
12953 }
12954 type ReplyType<'buf> = IterableOpQstatsGetDumpReply<'buf>;
12955 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
12956 OpQstatsGetDumpReply::new(buf)
12957 }
12958 fn lookup(
12959 buf: &[u8],
12960 offset: usize,
12961 missing_type: Option<u16>,
12962 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12963 OpQstatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
12964 }
12965}
12966#[doc = "Bind dmabuf to netdev"]
12967pub struct PushOpBindRxDoRequest<Prev: Rec> {
12968 pub(crate) prev: Option<Prev>,
12969 pub(crate) header_offset: Option<usize>,
12970}
12971impl<Prev: Rec> Rec for PushOpBindRxDoRequest<Prev> {
12972 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
12973 self.prev.as_mut().unwrap().as_rec_mut()
12974 }
12975 fn as_rec(&self) -> &Vec<u8> {
12976 self.prev.as_ref().unwrap().as_rec()
12977 }
12978}
12979impl<Prev: Rec> PushOpBindRxDoRequest<Prev> {
12980 pub fn new(mut prev: Prev) -> Self {
12981 Self::write_header(&mut prev);
12982 Self::new_without_header(prev)
12983 }
12984 fn new_without_header(prev: Prev) -> Self {
12985 Self {
12986 prev: Some(prev),
12987 header_offset: None,
12988 }
12989 }
12990 fn write_header(prev: &mut Prev) {
12991 let mut header = PushBuiltinNfgenmsg::new();
12992 header.set_cmd(13u8);
12993 header.set_version(1u8);
12994 prev.as_rec_mut().extend(header.as_slice());
12995 }
12996 pub fn end_nested(mut self) -> Prev {
12997 let mut prev = self.prev.take().unwrap();
12998 if let Some(header_offset) = &self.header_offset {
12999 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13000 }
13001 prev
13002 }
13003 #[doc = "netdev ifindex to bind the dmabuf to."]
13004 pub fn push_ifindex(mut self, value: u32) -> Self {
13005 push_header(self.as_rec_mut(), 1u16, 4 as u16);
13006 self.as_rec_mut().extend(value.to_ne_bytes());
13007 self
13008 }
13009 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13010 pub fn nested_queues(mut self) -> PushQueueId<Self> {
13011 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
13012 PushQueueId {
13013 prev: Some(self),
13014 header_offset: Some(header_offset),
13015 }
13016 }
13017 #[doc = "dmabuf file descriptor to bind."]
13018 pub fn push_fd(mut self, value: u32) -> Self {
13019 push_header(self.as_rec_mut(), 3u16, 4 as u16);
13020 self.as_rec_mut().extend(value.to_ne_bytes());
13021 self
13022 }
13023}
13024impl<Prev: Rec> Drop for PushOpBindRxDoRequest<Prev> {
13025 fn drop(&mut self) {
13026 if let Some(prev) = &mut self.prev {
13027 if let Some(header_offset) = &self.header_offset {
13028 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13029 }
13030 }
13031 }
13032}
13033#[doc = "Bind dmabuf to netdev"]
13034#[derive(Clone)]
13035pub enum OpBindRxDoRequest<'a> {
13036 #[doc = "netdev ifindex to bind the dmabuf to."]
13037 Ifindex(u32),
13038 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13039 Queues(IterableQueueId<'a>),
13040 #[doc = "dmabuf file descriptor to bind."]
13041 Fd(u32),
13042}
13043impl<'a> IterableOpBindRxDoRequest<'a> {
13044 #[doc = "netdev ifindex to bind the dmabuf to."]
13045 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
13046 let mut iter = self.clone();
13047 iter.pos = 0;
13048 for attr in iter {
13049 if let OpBindRxDoRequest::Ifindex(val) = attr? {
13050 return Ok(val);
13051 }
13052 }
13053 Err(ErrorContext::new_missing(
13054 "OpBindRxDoRequest",
13055 "Ifindex",
13056 self.orig_loc,
13057 self.buf.as_ptr() as usize,
13058 ))
13059 }
13060 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
13061 pub fn get_queues(
13062 &self,
13063 ) -> MultiAttrIterable<Self, OpBindRxDoRequest<'a>, IterableQueueId<'a>> {
13064 MultiAttrIterable::new(self.clone(), |variant| {
13065 if let OpBindRxDoRequest::Queues(val) = variant {
13066 Some(val)
13067 } else {
13068 None
13069 }
13070 })
13071 }
13072 #[doc = "dmabuf file descriptor to bind."]
13073 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
13074 let mut iter = self.clone();
13075 iter.pos = 0;
13076 for attr in iter {
13077 if let OpBindRxDoRequest::Fd(val) = attr? {
13078 return Ok(val);
13079 }
13080 }
13081 Err(ErrorContext::new_missing(
13082 "OpBindRxDoRequest",
13083 "Fd",
13084 self.orig_loc,
13085 self.buf.as_ptr() as usize,
13086 ))
13087 }
13088}
13089impl OpBindRxDoRequest<'_> {
13090 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoRequest<'a> {
13091 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13092 IterableOpBindRxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13093 }
13094 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13095 Dmabuf::attr_from_type(r#type)
13096 }
13097}
13098#[derive(Clone, Copy, Default)]
13099pub struct IterableOpBindRxDoRequest<'a> {
13100 buf: &'a [u8],
13101 pos: usize,
13102 orig_loc: usize,
13103}
13104impl<'a> IterableOpBindRxDoRequest<'a> {
13105 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13106 Self {
13107 buf,
13108 pos: 0,
13109 orig_loc,
13110 }
13111 }
13112 pub fn get_buf(&self) -> &'a [u8] {
13113 self.buf
13114 }
13115}
13116impl<'a> Iterator for IterableOpBindRxDoRequest<'a> {
13117 type Item = Result<OpBindRxDoRequest<'a>, ErrorContext>;
13118 fn next(&mut self) -> Option<Self::Item> {
13119 let pos = self.pos;
13120 let mut r#type;
13121 loop {
13122 r#type = None;
13123 if self.buf.len() == self.pos {
13124 return None;
13125 }
13126 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13127 break;
13128 };
13129 r#type = Some(header.r#type);
13130 let res = match header.r#type {
13131 1u16 => OpBindRxDoRequest::Ifindex({
13132 let res = parse_u32(next);
13133 let Some(val) = res else { break };
13134 val
13135 }),
13136 2u16 => OpBindRxDoRequest::Queues({
13137 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
13138 let Some(val) = res else { break };
13139 val
13140 }),
13141 3u16 => OpBindRxDoRequest::Fd({
13142 let res = parse_u32(next);
13143 let Some(val) = res else { break };
13144 val
13145 }),
13146 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13147 n => continue,
13148 };
13149 return Some(Ok(res));
13150 }
13151 Some(Err(ErrorContext::new(
13152 "OpBindRxDoRequest",
13153 r#type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13154 self.orig_loc,
13155 self.buf.as_ptr().wrapping_add(pos) as usize,
13156 )))
13157 }
13158}
13159impl<'a> std::fmt::Debug for IterableOpBindRxDoRequest<'_> {
13160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13161 let mut fmt = f.debug_struct("OpBindRxDoRequest");
13162 for attr in self.clone() {
13163 let attr = match attr {
13164 Ok(a) => a,
13165 Err(err) => {
13166 fmt.finish()?;
13167 f.write_str("Err(")?;
13168 err.fmt(f)?;
13169 return f.write_str(")");
13170 }
13171 };
13172 match attr {
13173 OpBindRxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
13174 OpBindRxDoRequest::Queues(val) => fmt.field("Queues", &val),
13175 OpBindRxDoRequest::Fd(val) => fmt.field("Fd", &val),
13176 };
13177 }
13178 fmt.finish()
13179 }
13180}
13181impl IterableOpBindRxDoRequest<'_> {
13182 pub fn lookup_attr(
13183 &self,
13184 offset: usize,
13185 missing_type: Option<u16>,
13186 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13187 let mut stack = Vec::new();
13188 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13189 if cur == offset + PushBuiltinNfgenmsg::len() {
13190 stack.push(("OpBindRxDoRequest", offset));
13191 return (
13192 stack,
13193 missing_type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13194 );
13195 }
13196 if cur > offset || cur + self.buf.len() < offset {
13197 return (stack, None);
13198 }
13199 let mut attrs = self.clone();
13200 let mut last_off = cur + attrs.pos;
13201 let mut missing = None;
13202 while let Some(attr) = attrs.next() {
13203 let Ok(attr) = attr else { break };
13204 match attr {
13205 OpBindRxDoRequest::Ifindex(val) => {
13206 if last_off == offset {
13207 stack.push(("Ifindex", last_off));
13208 break;
13209 }
13210 }
13211 OpBindRxDoRequest::Queues(val) => {
13212 (stack, missing) = val.lookup_attr(offset, missing_type);
13213 if !stack.is_empty() {
13214 break;
13215 }
13216 }
13217 OpBindRxDoRequest::Fd(val) => {
13218 if last_off == offset {
13219 stack.push(("Fd", last_off));
13220 break;
13221 }
13222 }
13223 _ => {}
13224 };
13225 last_off = cur + attrs.pos;
13226 }
13227 if !stack.is_empty() {
13228 stack.push(("OpBindRxDoRequest", cur));
13229 }
13230 (stack, missing)
13231 }
13232}
13233#[doc = "Bind dmabuf to netdev"]
13234pub struct PushOpBindRxDoReply<Prev: Rec> {
13235 pub(crate) prev: Option<Prev>,
13236 pub(crate) header_offset: Option<usize>,
13237}
13238impl<Prev: Rec> Rec for PushOpBindRxDoReply<Prev> {
13239 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13240 self.prev.as_mut().unwrap().as_rec_mut()
13241 }
13242 fn as_rec(&self) -> &Vec<u8> {
13243 self.prev.as_ref().unwrap().as_rec()
13244 }
13245}
13246impl<Prev: Rec> PushOpBindRxDoReply<Prev> {
13247 pub fn new(mut prev: Prev) -> Self {
13248 Self::write_header(&mut prev);
13249 Self::new_without_header(prev)
13250 }
13251 fn new_without_header(prev: Prev) -> Self {
13252 Self {
13253 prev: Some(prev),
13254 header_offset: None,
13255 }
13256 }
13257 fn write_header(prev: &mut Prev) {
13258 let mut header = PushBuiltinNfgenmsg::new();
13259 header.set_cmd(13u8);
13260 header.set_version(1u8);
13261 prev.as_rec_mut().extend(header.as_slice());
13262 }
13263 pub fn end_nested(mut self) -> Prev {
13264 let mut prev = self.prev.take().unwrap();
13265 if let Some(header_offset) = &self.header_offset {
13266 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13267 }
13268 prev
13269 }
13270 #[doc = "id of the dmabuf binding"]
13271 pub fn push_id(mut self, value: u32) -> Self {
13272 push_header(self.as_rec_mut(), 4u16, 4 as u16);
13273 self.as_rec_mut().extend(value.to_ne_bytes());
13274 self
13275 }
13276}
13277impl<Prev: Rec> Drop for PushOpBindRxDoReply<Prev> {
13278 fn drop(&mut self) {
13279 if let Some(prev) = &mut self.prev {
13280 if let Some(header_offset) = &self.header_offset {
13281 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13282 }
13283 }
13284 }
13285}
13286#[doc = "Bind dmabuf to netdev"]
13287#[derive(Clone)]
13288pub enum OpBindRxDoReply {
13289 #[doc = "id of the dmabuf binding"]
13290 Id(u32),
13291}
13292impl<'a> IterableOpBindRxDoReply<'a> {
13293 #[doc = "id of the dmabuf binding"]
13294 pub fn get_id(&self) -> Result<u32, ErrorContext> {
13295 let mut iter = self.clone();
13296 iter.pos = 0;
13297 for attr in iter {
13298 if let OpBindRxDoReply::Id(val) = attr? {
13299 return Ok(val);
13300 }
13301 }
13302 Err(ErrorContext::new_missing(
13303 "OpBindRxDoReply",
13304 "Id",
13305 self.orig_loc,
13306 self.buf.as_ptr() as usize,
13307 ))
13308 }
13309}
13310impl OpBindRxDoReply {
13311 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoReply<'a> {
13312 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13313 IterableOpBindRxDoReply::with_loc(attrs, buf.as_ptr() as usize)
13314 }
13315 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13316 Dmabuf::attr_from_type(r#type)
13317 }
13318}
13319#[derive(Clone, Copy, Default)]
13320pub struct IterableOpBindRxDoReply<'a> {
13321 buf: &'a [u8],
13322 pos: usize,
13323 orig_loc: usize,
13324}
13325impl<'a> IterableOpBindRxDoReply<'a> {
13326 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13327 Self {
13328 buf,
13329 pos: 0,
13330 orig_loc,
13331 }
13332 }
13333 pub fn get_buf(&self) -> &'a [u8] {
13334 self.buf
13335 }
13336}
13337impl<'a> Iterator for IterableOpBindRxDoReply<'a> {
13338 type Item = Result<OpBindRxDoReply, ErrorContext>;
13339 fn next(&mut self) -> Option<Self::Item> {
13340 let pos = self.pos;
13341 let mut r#type;
13342 loop {
13343 r#type = None;
13344 if self.buf.len() == self.pos {
13345 return None;
13346 }
13347 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13348 break;
13349 };
13350 r#type = Some(header.r#type);
13351 let res = match header.r#type {
13352 4u16 => OpBindRxDoReply::Id({
13353 let res = parse_u32(next);
13354 let Some(val) = res else { break };
13355 val
13356 }),
13357 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13358 n => continue,
13359 };
13360 return Some(Ok(res));
13361 }
13362 Some(Err(ErrorContext::new(
13363 "OpBindRxDoReply",
13364 r#type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13365 self.orig_loc,
13366 self.buf.as_ptr().wrapping_add(pos) as usize,
13367 )))
13368 }
13369}
13370impl std::fmt::Debug for IterableOpBindRxDoReply<'_> {
13371 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13372 let mut fmt = f.debug_struct("OpBindRxDoReply");
13373 for attr in self.clone() {
13374 let attr = match attr {
13375 Ok(a) => a,
13376 Err(err) => {
13377 fmt.finish()?;
13378 f.write_str("Err(")?;
13379 err.fmt(f)?;
13380 return f.write_str(")");
13381 }
13382 };
13383 match attr {
13384 OpBindRxDoReply::Id(val) => fmt.field("Id", &val),
13385 };
13386 }
13387 fmt.finish()
13388 }
13389}
13390impl IterableOpBindRxDoReply<'_> {
13391 pub fn lookup_attr(
13392 &self,
13393 offset: usize,
13394 missing_type: Option<u16>,
13395 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13396 let mut stack = Vec::new();
13397 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13398 if cur == offset + PushBuiltinNfgenmsg::len() {
13399 stack.push(("OpBindRxDoReply", offset));
13400 return (
13401 stack,
13402 missing_type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13403 );
13404 }
13405 if cur > offset || cur + self.buf.len() < offset {
13406 return (stack, None);
13407 }
13408 let mut attrs = self.clone();
13409 let mut last_off = cur + attrs.pos;
13410 while let Some(attr) = attrs.next() {
13411 let Ok(attr) = attr else { break };
13412 match attr {
13413 OpBindRxDoReply::Id(val) => {
13414 if last_off == offset {
13415 stack.push(("Id", last_off));
13416 break;
13417 }
13418 }
13419 _ => {}
13420 };
13421 last_off = cur + attrs.pos;
13422 }
13423 if !stack.is_empty() {
13424 stack.push(("OpBindRxDoReply", cur));
13425 }
13426 (stack, None)
13427 }
13428}
13429#[derive(Debug)]
13430pub struct RequestOpBindRxDoRequest<'r> {
13431 request: Request<'r>,
13432}
13433impl<'r> RequestOpBindRxDoRequest<'r> {
13434 pub fn new(mut request: Request<'r>) -> Self {
13435 PushOpBindRxDoRequest::write_header(&mut request.buf_mut());
13436 Self { request: request }
13437 }
13438 pub fn encode(&mut self) -> PushOpBindRxDoRequest<&mut Vec<u8>> {
13439 PushOpBindRxDoRequest::new_without_header(self.request.buf_mut())
13440 }
13441 pub fn into_encoder(self) -> PushOpBindRxDoRequest<RequestBuf<'r>> {
13442 PushOpBindRxDoRequest::new_without_header(self.request.buf)
13443 }
13444 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpBindRxDoRequest<'buf> {
13445 OpBindRxDoRequest::new(buf)
13446 }
13447}
13448impl NetlinkRequest for RequestOpBindRxDoRequest<'_> {
13449 fn protocol(&self) -> Protocol {
13450 Protocol::Generic("netdev".as_bytes())
13451 }
13452 fn flags(&self) -> u16 {
13453 self.request.flags
13454 }
13455 fn payload(&self) -> &[u8] {
13456 self.request.buf()
13457 }
13458 type ReplyType<'buf> = IterableOpBindRxDoReply<'buf>;
13459 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13460 OpBindRxDoReply::new(buf)
13461 }
13462 fn lookup(
13463 buf: &[u8],
13464 offset: usize,
13465 missing_type: Option<u16>,
13466 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13467 OpBindRxDoRequest::new(buf).lookup_attr(offset, missing_type)
13468 }
13469}
13470#[doc = "Set configurable NAPI instance settings."]
13471pub struct PushOpNapiSetDoRequest<Prev: Rec> {
13472 pub(crate) prev: Option<Prev>,
13473 pub(crate) header_offset: Option<usize>,
13474}
13475impl<Prev: Rec> Rec for PushOpNapiSetDoRequest<Prev> {
13476 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13477 self.prev.as_mut().unwrap().as_rec_mut()
13478 }
13479 fn as_rec(&self) -> &Vec<u8> {
13480 self.prev.as_ref().unwrap().as_rec()
13481 }
13482}
13483impl<Prev: Rec> PushOpNapiSetDoRequest<Prev> {
13484 pub fn new(mut prev: Prev) -> Self {
13485 Self::write_header(&mut prev);
13486 Self::new_without_header(prev)
13487 }
13488 fn new_without_header(prev: Prev) -> Self {
13489 Self {
13490 prev: Some(prev),
13491 header_offset: None,
13492 }
13493 }
13494 fn write_header(prev: &mut Prev) {
13495 let mut header = PushBuiltinNfgenmsg::new();
13496 header.set_cmd(14u8);
13497 header.set_version(1u8);
13498 prev.as_rec_mut().extend(header.as_slice());
13499 }
13500 pub fn end_nested(mut self) -> Prev {
13501 let mut prev = self.prev.take().unwrap();
13502 if let Some(header_offset) = &self.header_offset {
13503 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13504 }
13505 prev
13506 }
13507 #[doc = "ID of the NAPI instance."]
13508 pub fn push_id(mut self, value: u32) -> Self {
13509 push_header(self.as_rec_mut(), 2u16, 4 as u16);
13510 self.as_rec_mut().extend(value.to_ne_bytes());
13511 self
13512 }
13513 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13514 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
13515 push_header(self.as_rec_mut(), 5u16, 4 as u16);
13516 self.as_rec_mut().extend(value.to_ne_bytes());
13517 self
13518 }
13519 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13520 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
13521 push_header(self.as_rec_mut(), 6u16, 4 as u16);
13522 self.as_rec_mut().extend(value.to_ne_bytes());
13523 self
13524 }
13525 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13526 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
13527 push_header(self.as_rec_mut(), 7u16, 4 as u16);
13528 self.as_rec_mut().extend(value.to_ne_bytes());
13529 self
13530 }
13531 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13532 pub fn push_threaded(mut self, value: u32) -> Self {
13533 push_header(self.as_rec_mut(), 8u16, 4 as u16);
13534 self.as_rec_mut().extend(value.to_ne_bytes());
13535 self
13536 }
13537}
13538impl<Prev: Rec> Drop for PushOpNapiSetDoRequest<Prev> {
13539 fn drop(&mut self) {
13540 if let Some(prev) = &mut self.prev {
13541 if let Some(header_offset) = &self.header_offset {
13542 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13543 }
13544 }
13545 }
13546}
13547#[doc = "Set configurable NAPI instance settings."]
13548#[derive(Clone)]
13549pub enum OpNapiSetDoRequest {
13550 #[doc = "ID of the NAPI instance."]
13551 Id(u32),
13552 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13553 DeferHardIrqs(u32),
13554 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13555 GroFlushTimeout(u32),
13556 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13557 IrqSuspendTimeout(u32),
13558 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13559 Threaded(u32),
13560}
13561impl<'a> IterableOpNapiSetDoRequest<'a> {
13562 #[doc = "ID of the NAPI instance."]
13563 pub fn get_id(&self) -> Result<u32, ErrorContext> {
13564 let mut iter = self.clone();
13565 iter.pos = 0;
13566 for attr in iter {
13567 if let OpNapiSetDoRequest::Id(val) = attr? {
13568 return Ok(val);
13569 }
13570 }
13571 Err(ErrorContext::new_missing(
13572 "OpNapiSetDoRequest",
13573 "Id",
13574 self.orig_loc,
13575 self.buf.as_ptr() as usize,
13576 ))
13577 }
13578 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13579 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
13580 let mut iter = self.clone();
13581 iter.pos = 0;
13582 for attr in iter {
13583 if let OpNapiSetDoRequest::DeferHardIrqs(val) = attr? {
13584 return Ok(val);
13585 }
13586 }
13587 Err(ErrorContext::new_missing(
13588 "OpNapiSetDoRequest",
13589 "DeferHardIrqs",
13590 self.orig_loc,
13591 self.buf.as_ptr() as usize,
13592 ))
13593 }
13594 #[doc = "The timeout, in nanoseconds, of when to trigger the NAPI watchdog timer which schedules NAPI processing. Additionally, a non-zero value will also prevent GRO from flushing recent super-frames at the end of a NAPI cycle. This may add receive latency in exchange for reducing the number of frames processed by the network stack."]
13595 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
13596 let mut iter = self.clone();
13597 iter.pos = 0;
13598 for attr in iter {
13599 if let OpNapiSetDoRequest::GroFlushTimeout(val) = attr? {
13600 return Ok(val);
13601 }
13602 }
13603 Err(ErrorContext::new_missing(
13604 "OpNapiSetDoRequest",
13605 "GroFlushTimeout",
13606 self.orig_loc,
13607 self.buf.as_ptr() as usize,
13608 ))
13609 }
13610 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13611 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
13612 let mut iter = self.clone();
13613 iter.pos = 0;
13614 for attr in iter {
13615 if let OpNapiSetDoRequest::IrqSuspendTimeout(val) = attr? {
13616 return Ok(val);
13617 }
13618 }
13619 Err(ErrorContext::new_missing(
13620 "OpNapiSetDoRequest",
13621 "IrqSuspendTimeout",
13622 self.orig_loc,
13623 self.buf.as_ptr() as usize,
13624 ))
13625 }
13626 #[doc = "Whether the NAPI is configured to operate in threaded polling mode. If this is set to enabled then the NAPI context operates in threaded polling mode. If this is set to busy-poll, then the threaded polling mode also busy polls.\nAssociated type: \"NapiThreaded\" (enum)"]
13627 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
13628 let mut iter = self.clone();
13629 iter.pos = 0;
13630 for attr in iter {
13631 if let OpNapiSetDoRequest::Threaded(val) = attr? {
13632 return Ok(val);
13633 }
13634 }
13635 Err(ErrorContext::new_missing(
13636 "OpNapiSetDoRequest",
13637 "Threaded",
13638 self.orig_loc,
13639 self.buf.as_ptr() as usize,
13640 ))
13641 }
13642}
13643impl OpNapiSetDoRequest {
13644 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoRequest<'a> {
13645 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13646 IterableOpNapiSetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13647 }
13648 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13649 Napi::attr_from_type(r#type)
13650 }
13651}
13652#[derive(Clone, Copy, Default)]
13653pub struct IterableOpNapiSetDoRequest<'a> {
13654 buf: &'a [u8],
13655 pos: usize,
13656 orig_loc: usize,
13657}
13658impl<'a> IterableOpNapiSetDoRequest<'a> {
13659 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13660 Self {
13661 buf,
13662 pos: 0,
13663 orig_loc,
13664 }
13665 }
13666 pub fn get_buf(&self) -> &'a [u8] {
13667 self.buf
13668 }
13669}
13670impl<'a> Iterator for IterableOpNapiSetDoRequest<'a> {
13671 type Item = Result<OpNapiSetDoRequest, ErrorContext>;
13672 fn next(&mut self) -> Option<Self::Item> {
13673 let pos = self.pos;
13674 let mut r#type;
13675 loop {
13676 r#type = None;
13677 if self.buf.len() == self.pos {
13678 return None;
13679 }
13680 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13681 break;
13682 };
13683 r#type = Some(header.r#type);
13684 let res = match header.r#type {
13685 2u16 => OpNapiSetDoRequest::Id({
13686 let res = parse_u32(next);
13687 let Some(val) = res else { break };
13688 val
13689 }),
13690 5u16 => OpNapiSetDoRequest::DeferHardIrqs({
13691 let res = parse_u32(next);
13692 let Some(val) = res else { break };
13693 val
13694 }),
13695 6u16 => OpNapiSetDoRequest::GroFlushTimeout({
13696 let res = parse_u32(next);
13697 let Some(val) = res else { break };
13698 val
13699 }),
13700 7u16 => OpNapiSetDoRequest::IrqSuspendTimeout({
13701 let res = parse_u32(next);
13702 let Some(val) = res else { break };
13703 val
13704 }),
13705 8u16 => OpNapiSetDoRequest::Threaded({
13706 let res = parse_u32(next);
13707 let Some(val) = res else { break };
13708 val
13709 }),
13710 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13711 n => continue,
13712 };
13713 return Some(Ok(res));
13714 }
13715 Some(Err(ErrorContext::new(
13716 "OpNapiSetDoRequest",
13717 r#type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13718 self.orig_loc,
13719 self.buf.as_ptr().wrapping_add(pos) as usize,
13720 )))
13721 }
13722}
13723impl std::fmt::Debug for IterableOpNapiSetDoRequest<'_> {
13724 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13725 let mut fmt = f.debug_struct("OpNapiSetDoRequest");
13726 for attr in self.clone() {
13727 let attr = match attr {
13728 Ok(a) => a,
13729 Err(err) => {
13730 fmt.finish()?;
13731 f.write_str("Err(")?;
13732 err.fmt(f)?;
13733 return f.write_str(")");
13734 }
13735 };
13736 match attr {
13737 OpNapiSetDoRequest::Id(val) => fmt.field("Id", &val),
13738 OpNapiSetDoRequest::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
13739 OpNapiSetDoRequest::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
13740 OpNapiSetDoRequest::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
13741 OpNapiSetDoRequest::Threaded(val) => fmt.field(
13742 "Threaded",
13743 &FormatEnum(val.into(), NapiThreaded::from_value),
13744 ),
13745 };
13746 }
13747 fmt.finish()
13748 }
13749}
13750impl IterableOpNapiSetDoRequest<'_> {
13751 pub fn lookup_attr(
13752 &self,
13753 offset: usize,
13754 missing_type: Option<u16>,
13755 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13756 let mut stack = Vec::new();
13757 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13758 if cur == offset + PushBuiltinNfgenmsg::len() {
13759 stack.push(("OpNapiSetDoRequest", offset));
13760 return (
13761 stack,
13762 missing_type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13763 );
13764 }
13765 if cur > offset || cur + self.buf.len() < offset {
13766 return (stack, None);
13767 }
13768 let mut attrs = self.clone();
13769 let mut last_off = cur + attrs.pos;
13770 while let Some(attr) = attrs.next() {
13771 let Ok(attr) = attr else { break };
13772 match attr {
13773 OpNapiSetDoRequest::Id(val) => {
13774 if last_off == offset {
13775 stack.push(("Id", last_off));
13776 break;
13777 }
13778 }
13779 OpNapiSetDoRequest::DeferHardIrqs(val) => {
13780 if last_off == offset {
13781 stack.push(("DeferHardIrqs", last_off));
13782 break;
13783 }
13784 }
13785 OpNapiSetDoRequest::GroFlushTimeout(val) => {
13786 if last_off == offset {
13787 stack.push(("GroFlushTimeout", last_off));
13788 break;
13789 }
13790 }
13791 OpNapiSetDoRequest::IrqSuspendTimeout(val) => {
13792 if last_off == offset {
13793 stack.push(("IrqSuspendTimeout", last_off));
13794 break;
13795 }
13796 }
13797 OpNapiSetDoRequest::Threaded(val) => {
13798 if last_off == offset {
13799 stack.push(("Threaded", last_off));
13800 break;
13801 }
13802 }
13803 _ => {}
13804 };
13805 last_off = cur + attrs.pos;
13806 }
13807 if !stack.is_empty() {
13808 stack.push(("OpNapiSetDoRequest", cur));
13809 }
13810 (stack, None)
13811 }
13812}
13813#[doc = "Set configurable NAPI instance settings."]
13814pub struct PushOpNapiSetDoReply<Prev: Rec> {
13815 pub(crate) prev: Option<Prev>,
13816 pub(crate) header_offset: Option<usize>,
13817}
13818impl<Prev: Rec> Rec for PushOpNapiSetDoReply<Prev> {
13819 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13820 self.prev.as_mut().unwrap().as_rec_mut()
13821 }
13822 fn as_rec(&self) -> &Vec<u8> {
13823 self.prev.as_ref().unwrap().as_rec()
13824 }
13825}
13826impl<Prev: Rec> PushOpNapiSetDoReply<Prev> {
13827 pub fn new(mut prev: Prev) -> Self {
13828 Self::write_header(&mut prev);
13829 Self::new_without_header(prev)
13830 }
13831 fn new_without_header(prev: Prev) -> Self {
13832 Self {
13833 prev: Some(prev),
13834 header_offset: None,
13835 }
13836 }
13837 fn write_header(prev: &mut Prev) {
13838 let mut header = PushBuiltinNfgenmsg::new();
13839 header.set_cmd(14u8);
13840 header.set_version(1u8);
13841 prev.as_rec_mut().extend(header.as_slice());
13842 }
13843 pub fn end_nested(mut self) -> Prev {
13844 let mut prev = self.prev.take().unwrap();
13845 if let Some(header_offset) = &self.header_offset {
13846 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13847 }
13848 prev
13849 }
13850}
13851impl<Prev: Rec> Drop for PushOpNapiSetDoReply<Prev> {
13852 fn drop(&mut self) {
13853 if let Some(prev) = &mut self.prev {
13854 if let Some(header_offset) = &self.header_offset {
13855 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13856 }
13857 }
13858 }
13859}
13860#[doc = "Set configurable NAPI instance settings."]
13861#[derive(Clone)]
13862pub enum OpNapiSetDoReply {}
13863impl<'a> IterableOpNapiSetDoReply<'a> {}
13864impl OpNapiSetDoReply {
13865 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoReply<'a> {
13866 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13867 IterableOpNapiSetDoReply::with_loc(attrs, buf.as_ptr() as usize)
13868 }
13869 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13870 Napi::attr_from_type(r#type)
13871 }
13872}
13873#[derive(Clone, Copy, Default)]
13874pub struct IterableOpNapiSetDoReply<'a> {
13875 buf: &'a [u8],
13876 pos: usize,
13877 orig_loc: usize,
13878}
13879impl<'a> IterableOpNapiSetDoReply<'a> {
13880 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13881 Self {
13882 buf,
13883 pos: 0,
13884 orig_loc,
13885 }
13886 }
13887 pub fn get_buf(&self) -> &'a [u8] {
13888 self.buf
13889 }
13890}
13891impl<'a> Iterator for IterableOpNapiSetDoReply<'a> {
13892 type Item = Result<OpNapiSetDoReply, ErrorContext>;
13893 fn next(&mut self) -> Option<Self::Item> {
13894 let pos = self.pos;
13895 let mut r#type;
13896 loop {
13897 r#type = None;
13898 if self.buf.len() == self.pos {
13899 return None;
13900 }
13901 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
13902 break;
13903 };
13904 r#type = Some(header.r#type);
13905 let res = match header.r#type {
13906 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
13907 n => continue,
13908 };
13909 return Some(Ok(res));
13910 }
13911 Some(Err(ErrorContext::new(
13912 "OpNapiSetDoReply",
13913 r#type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13914 self.orig_loc,
13915 self.buf.as_ptr().wrapping_add(pos) as usize,
13916 )))
13917 }
13918}
13919impl std::fmt::Debug for IterableOpNapiSetDoReply<'_> {
13920 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13921 let mut fmt = f.debug_struct("OpNapiSetDoReply");
13922 for attr in self.clone() {
13923 let attr = match attr {
13924 Ok(a) => a,
13925 Err(err) => {
13926 fmt.finish()?;
13927 f.write_str("Err(")?;
13928 err.fmt(f)?;
13929 return f.write_str(")");
13930 }
13931 };
13932 match attr {};
13933 }
13934 fmt.finish()
13935 }
13936}
13937impl IterableOpNapiSetDoReply<'_> {
13938 pub fn lookup_attr(
13939 &self,
13940 offset: usize,
13941 missing_type: Option<u16>,
13942 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13943 let mut stack = Vec::new();
13944 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13945 if cur == offset + PushBuiltinNfgenmsg::len() {
13946 stack.push(("OpNapiSetDoReply", offset));
13947 return (
13948 stack,
13949 missing_type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13950 );
13951 }
13952 (stack, None)
13953 }
13954}
13955#[derive(Debug)]
13956pub struct RequestOpNapiSetDoRequest<'r> {
13957 request: Request<'r>,
13958}
13959impl<'r> RequestOpNapiSetDoRequest<'r> {
13960 pub fn new(mut request: Request<'r>) -> Self {
13961 PushOpNapiSetDoRequest::write_header(&mut request.buf_mut());
13962 Self { request: request }
13963 }
13964 pub fn encode(&mut self) -> PushOpNapiSetDoRequest<&mut Vec<u8>> {
13965 PushOpNapiSetDoRequest::new_without_header(self.request.buf_mut())
13966 }
13967 pub fn into_encoder(self) -> PushOpNapiSetDoRequest<RequestBuf<'r>> {
13968 PushOpNapiSetDoRequest::new_without_header(self.request.buf)
13969 }
13970 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpNapiSetDoRequest<'buf> {
13971 OpNapiSetDoRequest::new(buf)
13972 }
13973}
13974impl NetlinkRequest for RequestOpNapiSetDoRequest<'_> {
13975 fn protocol(&self) -> Protocol {
13976 Protocol::Generic("netdev".as_bytes())
13977 }
13978 fn flags(&self) -> u16 {
13979 self.request.flags
13980 }
13981 fn payload(&self) -> &[u8] {
13982 self.request.buf()
13983 }
13984 type ReplyType<'buf> = IterableOpNapiSetDoReply<'buf>;
13985 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13986 OpNapiSetDoReply::new(buf)
13987 }
13988 fn lookup(
13989 buf: &[u8],
13990 offset: usize,
13991 missing_type: Option<u16>,
13992 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13993 OpNapiSetDoRequest::new(buf).lookup_attr(offset, missing_type)
13994 }
13995}
13996#[doc = "Bind dmabuf to netdev for TX"]
13997pub struct PushOpBindTxDoRequest<Prev: Rec> {
13998 pub(crate) prev: Option<Prev>,
13999 pub(crate) header_offset: Option<usize>,
14000}
14001impl<Prev: Rec> Rec for PushOpBindTxDoRequest<Prev> {
14002 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14003 self.prev.as_mut().unwrap().as_rec_mut()
14004 }
14005 fn as_rec(&self) -> &Vec<u8> {
14006 self.prev.as_ref().unwrap().as_rec()
14007 }
14008}
14009impl<Prev: Rec> PushOpBindTxDoRequest<Prev> {
14010 pub fn new(mut prev: Prev) -> Self {
14011 Self::write_header(&mut prev);
14012 Self::new_without_header(prev)
14013 }
14014 fn new_without_header(prev: Prev) -> Self {
14015 Self {
14016 prev: Some(prev),
14017 header_offset: None,
14018 }
14019 }
14020 fn write_header(prev: &mut Prev) {
14021 let mut header = PushBuiltinNfgenmsg::new();
14022 header.set_cmd(15u8);
14023 header.set_version(1u8);
14024 prev.as_rec_mut().extend(header.as_slice());
14025 }
14026 pub fn end_nested(mut self) -> Prev {
14027 let mut prev = self.prev.take().unwrap();
14028 if let Some(header_offset) = &self.header_offset {
14029 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14030 }
14031 prev
14032 }
14033 #[doc = "netdev ifindex to bind the dmabuf to."]
14034 pub fn push_ifindex(mut self, value: u32) -> Self {
14035 push_header(self.as_rec_mut(), 1u16, 4 as u16);
14036 self.as_rec_mut().extend(value.to_ne_bytes());
14037 self
14038 }
14039 #[doc = "dmabuf file descriptor to bind."]
14040 pub fn push_fd(mut self, value: u32) -> Self {
14041 push_header(self.as_rec_mut(), 3u16, 4 as u16);
14042 self.as_rec_mut().extend(value.to_ne_bytes());
14043 self
14044 }
14045}
14046impl<Prev: Rec> Drop for PushOpBindTxDoRequest<Prev> {
14047 fn drop(&mut self) {
14048 if let Some(prev) = &mut self.prev {
14049 if let Some(header_offset) = &self.header_offset {
14050 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14051 }
14052 }
14053 }
14054}
14055#[doc = "Bind dmabuf to netdev for TX"]
14056#[derive(Clone)]
14057pub enum OpBindTxDoRequest {
14058 #[doc = "netdev ifindex to bind the dmabuf to."]
14059 Ifindex(u32),
14060 #[doc = "dmabuf file descriptor to bind."]
14061 Fd(u32),
14062}
14063impl<'a> IterableOpBindTxDoRequest<'a> {
14064 #[doc = "netdev ifindex to bind the dmabuf to."]
14065 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
14066 let mut iter = self.clone();
14067 iter.pos = 0;
14068 for attr in iter {
14069 if let OpBindTxDoRequest::Ifindex(val) = attr? {
14070 return Ok(val);
14071 }
14072 }
14073 Err(ErrorContext::new_missing(
14074 "OpBindTxDoRequest",
14075 "Ifindex",
14076 self.orig_loc,
14077 self.buf.as_ptr() as usize,
14078 ))
14079 }
14080 #[doc = "dmabuf file descriptor to bind."]
14081 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
14082 let mut iter = self.clone();
14083 iter.pos = 0;
14084 for attr in iter {
14085 if let OpBindTxDoRequest::Fd(val) = attr? {
14086 return Ok(val);
14087 }
14088 }
14089 Err(ErrorContext::new_missing(
14090 "OpBindTxDoRequest",
14091 "Fd",
14092 self.orig_loc,
14093 self.buf.as_ptr() as usize,
14094 ))
14095 }
14096}
14097impl OpBindTxDoRequest {
14098 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoRequest<'a> {
14099 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14100 IterableOpBindTxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
14101 }
14102 fn attr_from_type(r#type: u16) -> Option<&'static str> {
14103 Dmabuf::attr_from_type(r#type)
14104 }
14105}
14106#[derive(Clone, Copy, Default)]
14107pub struct IterableOpBindTxDoRequest<'a> {
14108 buf: &'a [u8],
14109 pos: usize,
14110 orig_loc: usize,
14111}
14112impl<'a> IterableOpBindTxDoRequest<'a> {
14113 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14114 Self {
14115 buf,
14116 pos: 0,
14117 orig_loc,
14118 }
14119 }
14120 pub fn get_buf(&self) -> &'a [u8] {
14121 self.buf
14122 }
14123}
14124impl<'a> Iterator for IterableOpBindTxDoRequest<'a> {
14125 type Item = Result<OpBindTxDoRequest, ErrorContext>;
14126 fn next(&mut self) -> Option<Self::Item> {
14127 let pos = self.pos;
14128 let mut r#type;
14129 loop {
14130 r#type = None;
14131 if self.buf.len() == self.pos {
14132 return None;
14133 }
14134 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
14135 break;
14136 };
14137 r#type = Some(header.r#type);
14138 let res = match header.r#type {
14139 1u16 => OpBindTxDoRequest::Ifindex({
14140 let res = parse_u32(next);
14141 let Some(val) = res else { break };
14142 val
14143 }),
14144 3u16 => OpBindTxDoRequest::Fd({
14145 let res = parse_u32(next);
14146 let Some(val) = res else { break };
14147 val
14148 }),
14149 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
14150 n => continue,
14151 };
14152 return Some(Ok(res));
14153 }
14154 Some(Err(ErrorContext::new(
14155 "OpBindTxDoRequest",
14156 r#type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14157 self.orig_loc,
14158 self.buf.as_ptr().wrapping_add(pos) as usize,
14159 )))
14160 }
14161}
14162impl std::fmt::Debug for IterableOpBindTxDoRequest<'_> {
14163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14164 let mut fmt = f.debug_struct("OpBindTxDoRequest");
14165 for attr in self.clone() {
14166 let attr = match attr {
14167 Ok(a) => a,
14168 Err(err) => {
14169 fmt.finish()?;
14170 f.write_str("Err(")?;
14171 err.fmt(f)?;
14172 return f.write_str(")");
14173 }
14174 };
14175 match attr {
14176 OpBindTxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
14177 OpBindTxDoRequest::Fd(val) => fmt.field("Fd", &val),
14178 };
14179 }
14180 fmt.finish()
14181 }
14182}
14183impl IterableOpBindTxDoRequest<'_> {
14184 pub fn lookup_attr(
14185 &self,
14186 offset: usize,
14187 missing_type: Option<u16>,
14188 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14189 let mut stack = Vec::new();
14190 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14191 if cur == offset + PushBuiltinNfgenmsg::len() {
14192 stack.push(("OpBindTxDoRequest", offset));
14193 return (
14194 stack,
14195 missing_type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14196 );
14197 }
14198 if cur > offset || cur + self.buf.len() < offset {
14199 return (stack, None);
14200 }
14201 let mut attrs = self.clone();
14202 let mut last_off = cur + attrs.pos;
14203 while let Some(attr) = attrs.next() {
14204 let Ok(attr) = attr else { break };
14205 match attr {
14206 OpBindTxDoRequest::Ifindex(val) => {
14207 if last_off == offset {
14208 stack.push(("Ifindex", last_off));
14209 break;
14210 }
14211 }
14212 OpBindTxDoRequest::Fd(val) => {
14213 if last_off == offset {
14214 stack.push(("Fd", last_off));
14215 break;
14216 }
14217 }
14218 _ => {}
14219 };
14220 last_off = cur + attrs.pos;
14221 }
14222 if !stack.is_empty() {
14223 stack.push(("OpBindTxDoRequest", cur));
14224 }
14225 (stack, None)
14226 }
14227}
14228#[doc = "Bind dmabuf to netdev for TX"]
14229pub struct PushOpBindTxDoReply<Prev: Rec> {
14230 pub(crate) prev: Option<Prev>,
14231 pub(crate) header_offset: Option<usize>,
14232}
14233impl<Prev: Rec> Rec for PushOpBindTxDoReply<Prev> {
14234 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14235 self.prev.as_mut().unwrap().as_rec_mut()
14236 }
14237 fn as_rec(&self) -> &Vec<u8> {
14238 self.prev.as_ref().unwrap().as_rec()
14239 }
14240}
14241impl<Prev: Rec> PushOpBindTxDoReply<Prev> {
14242 pub fn new(mut prev: Prev) -> Self {
14243 Self::write_header(&mut prev);
14244 Self::new_without_header(prev)
14245 }
14246 fn new_without_header(prev: Prev) -> Self {
14247 Self {
14248 prev: Some(prev),
14249 header_offset: None,
14250 }
14251 }
14252 fn write_header(prev: &mut Prev) {
14253 let mut header = PushBuiltinNfgenmsg::new();
14254 header.set_cmd(15u8);
14255 header.set_version(1u8);
14256 prev.as_rec_mut().extend(header.as_slice());
14257 }
14258 pub fn end_nested(mut self) -> Prev {
14259 let mut prev = self.prev.take().unwrap();
14260 if let Some(header_offset) = &self.header_offset {
14261 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14262 }
14263 prev
14264 }
14265 #[doc = "id of the dmabuf binding"]
14266 pub fn push_id(mut self, value: u32) -> Self {
14267 push_header(self.as_rec_mut(), 4u16, 4 as u16);
14268 self.as_rec_mut().extend(value.to_ne_bytes());
14269 self
14270 }
14271}
14272impl<Prev: Rec> Drop for PushOpBindTxDoReply<Prev> {
14273 fn drop(&mut self) {
14274 if let Some(prev) = &mut self.prev {
14275 if let Some(header_offset) = &self.header_offset {
14276 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14277 }
14278 }
14279 }
14280}
14281#[doc = "Bind dmabuf to netdev for TX"]
14282#[derive(Clone)]
14283pub enum OpBindTxDoReply {
14284 #[doc = "id of the dmabuf binding"]
14285 Id(u32),
14286}
14287impl<'a> IterableOpBindTxDoReply<'a> {
14288 #[doc = "id of the dmabuf binding"]
14289 pub fn get_id(&self) -> Result<u32, ErrorContext> {
14290 let mut iter = self.clone();
14291 iter.pos = 0;
14292 for attr in iter {
14293 if let OpBindTxDoReply::Id(val) = attr? {
14294 return Ok(val);
14295 }
14296 }
14297 Err(ErrorContext::new_missing(
14298 "OpBindTxDoReply",
14299 "Id",
14300 self.orig_loc,
14301 self.buf.as_ptr() as usize,
14302 ))
14303 }
14304}
14305impl OpBindTxDoReply {
14306 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoReply<'a> {
14307 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14308 IterableOpBindTxDoReply::with_loc(attrs, buf.as_ptr() as usize)
14309 }
14310 fn attr_from_type(r#type: u16) -> Option<&'static str> {
14311 Dmabuf::attr_from_type(r#type)
14312 }
14313}
14314#[derive(Clone, Copy, Default)]
14315pub struct IterableOpBindTxDoReply<'a> {
14316 buf: &'a [u8],
14317 pos: usize,
14318 orig_loc: usize,
14319}
14320impl<'a> IterableOpBindTxDoReply<'a> {
14321 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14322 Self {
14323 buf,
14324 pos: 0,
14325 orig_loc,
14326 }
14327 }
14328 pub fn get_buf(&self) -> &'a [u8] {
14329 self.buf
14330 }
14331}
14332impl<'a> Iterator for IterableOpBindTxDoReply<'a> {
14333 type Item = Result<OpBindTxDoReply, ErrorContext>;
14334 fn next(&mut self) -> Option<Self::Item> {
14335 let pos = self.pos;
14336 let mut r#type;
14337 loop {
14338 r#type = None;
14339 if self.buf.len() == self.pos {
14340 return None;
14341 }
14342 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
14343 break;
14344 };
14345 r#type = Some(header.r#type);
14346 let res = match header.r#type {
14347 4u16 => OpBindTxDoReply::Id({
14348 let res = parse_u32(next);
14349 let Some(val) = res else { break };
14350 val
14351 }),
14352 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
14353 n => continue,
14354 };
14355 return Some(Ok(res));
14356 }
14357 Some(Err(ErrorContext::new(
14358 "OpBindTxDoReply",
14359 r#type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14360 self.orig_loc,
14361 self.buf.as_ptr().wrapping_add(pos) as usize,
14362 )))
14363 }
14364}
14365impl std::fmt::Debug for IterableOpBindTxDoReply<'_> {
14366 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14367 let mut fmt = f.debug_struct("OpBindTxDoReply");
14368 for attr in self.clone() {
14369 let attr = match attr {
14370 Ok(a) => a,
14371 Err(err) => {
14372 fmt.finish()?;
14373 f.write_str("Err(")?;
14374 err.fmt(f)?;
14375 return f.write_str(")");
14376 }
14377 };
14378 match attr {
14379 OpBindTxDoReply::Id(val) => fmt.field("Id", &val),
14380 };
14381 }
14382 fmt.finish()
14383 }
14384}
14385impl IterableOpBindTxDoReply<'_> {
14386 pub fn lookup_attr(
14387 &self,
14388 offset: usize,
14389 missing_type: Option<u16>,
14390 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14391 let mut stack = Vec::new();
14392 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14393 if cur == offset + PushBuiltinNfgenmsg::len() {
14394 stack.push(("OpBindTxDoReply", offset));
14395 return (
14396 stack,
14397 missing_type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14398 );
14399 }
14400 if cur > offset || cur + self.buf.len() < offset {
14401 return (stack, None);
14402 }
14403 let mut attrs = self.clone();
14404 let mut last_off = cur + attrs.pos;
14405 while let Some(attr) = attrs.next() {
14406 let Ok(attr) = attr else { break };
14407 match attr {
14408 OpBindTxDoReply::Id(val) => {
14409 if last_off == offset {
14410 stack.push(("Id", last_off));
14411 break;
14412 }
14413 }
14414 _ => {}
14415 };
14416 last_off = cur + attrs.pos;
14417 }
14418 if !stack.is_empty() {
14419 stack.push(("OpBindTxDoReply", cur));
14420 }
14421 (stack, None)
14422 }
14423}
14424#[derive(Debug)]
14425pub struct RequestOpBindTxDoRequest<'r> {
14426 request: Request<'r>,
14427}
14428impl<'r> RequestOpBindTxDoRequest<'r> {
14429 pub fn new(mut request: Request<'r>) -> Self {
14430 PushOpBindTxDoRequest::write_header(&mut request.buf_mut());
14431 Self { request: request }
14432 }
14433 pub fn encode(&mut self) -> PushOpBindTxDoRequest<&mut Vec<u8>> {
14434 PushOpBindTxDoRequest::new_without_header(self.request.buf_mut())
14435 }
14436 pub fn into_encoder(self) -> PushOpBindTxDoRequest<RequestBuf<'r>> {
14437 PushOpBindTxDoRequest::new_without_header(self.request.buf)
14438 }
14439 pub fn decode_request<'buf>(buf: &'buf [u8]) -> IterableOpBindTxDoRequest<'buf> {
14440 OpBindTxDoRequest::new(buf)
14441 }
14442}
14443impl NetlinkRequest for RequestOpBindTxDoRequest<'_> {
14444 fn protocol(&self) -> Protocol {
14445 Protocol::Generic("netdev".as_bytes())
14446 }
14447 fn flags(&self) -> u16 {
14448 self.request.flags
14449 }
14450 fn payload(&self) -> &[u8] {
14451 self.request.buf()
14452 }
14453 type ReplyType<'buf> = IterableOpBindTxDoReply<'buf>;
14454 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
14455 OpBindTxDoReply::new(buf)
14456 }
14457 fn lookup(
14458 buf: &[u8],
14459 offset: usize,
14460 missing_type: Option<u16>,
14461 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14462 OpBindTxDoRequest::new(buf).lookup_attr(offset, missing_type)
14463 }
14464}
14465use crate::traits::LookupFn;
14466use crate::utils::RequestBuf;
14467#[derive(Debug)]
14468pub struct Request<'buf> {
14469 buf: RequestBuf<'buf>,
14470 flags: u16,
14471 writeback: Option<&'buf mut Option<RequestInfo>>,
14472}
14473#[allow(unused)]
14474#[derive(Debug, Clone)]
14475pub struct RequestInfo {
14476 protocol: Protocol,
14477 flags: u16,
14478 name: &'static str,
14479 lookup: LookupFn,
14480}
14481impl Request<'static> {
14482 pub fn new() -> Self {
14483 Self::new_from_buf(Vec::new())
14484 }
14485 pub fn new_from_buf(buf: Vec<u8>) -> Self {
14486 Self {
14487 flags: 0,
14488 buf: RequestBuf::Own(buf),
14489 writeback: None,
14490 }
14491 }
14492 pub fn into_buf(self) -> Vec<u8> {
14493 match self.buf {
14494 RequestBuf::Own(buf) => buf,
14495 _ => unreachable!(),
14496 }
14497 }
14498}
14499impl<'buf> Request<'buf> {
14500 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
14501 buf.clear();
14502 Self::new_extend(buf)
14503 }
14504 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
14505 Self {
14506 flags: 0,
14507 buf: RequestBuf::Ref(buf),
14508 writeback: None,
14509 }
14510 }
14511 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
14512 let Some(writeback) = &mut self.writeback else {
14513 return;
14514 };
14515 **writeback = Some(RequestInfo {
14516 protocol,
14517 flags: self.flags,
14518 name,
14519 lookup,
14520 })
14521 }
14522 pub fn buf(&self) -> &Vec<u8> {
14523 self.buf.buf()
14524 }
14525 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
14526 self.buf.buf_mut()
14527 }
14528 #[doc = "Set `NLM_F_CREATE` flag"]
14529 pub fn set_create(mut self) -> Self {
14530 self.flags |= consts::NLM_F_CREATE as u16;
14531 self
14532 }
14533 #[doc = "Set `NLM_F_EXCL` flag"]
14534 pub fn set_excl(mut self) -> Self {
14535 self.flags |= consts::NLM_F_EXCL as u16;
14536 self
14537 }
14538 #[doc = "Set `NLM_F_REPLACE` flag"]
14539 pub fn set_replace(mut self) -> Self {
14540 self.flags |= consts::NLM_F_REPLACE as u16;
14541 self
14542 }
14543 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
14544 pub fn set_change(self) -> Self {
14545 self.set_create().set_replace()
14546 }
14547 #[doc = "Set `NLM_F_APPEND` flag"]
14548 pub fn set_append(mut self) -> Self {
14549 self.flags |= consts::NLM_F_APPEND as u16;
14550 self
14551 }
14552 #[doc = "Set `NLM_F_DUMP` flag"]
14553 fn set_dump(mut self) -> Self {
14554 self.flags |= consts::NLM_F_DUMP as u16;
14555 self
14556 }
14557 pub fn op_dev_get_dump_request(self) -> RequestOpDevGetDumpRequest<'buf> {
14558 let mut res = RequestOpDevGetDumpRequest::new(self);
14559 res.request.do_writeback(
14560 res.protocol(),
14561 "op-dev-get-dump-request",
14562 RequestOpDevGetDumpRequest::lookup,
14563 );
14564 res
14565 }
14566 pub fn op_dev_get_do_request(self) -> RequestOpDevGetDoRequest<'buf> {
14567 let mut res = RequestOpDevGetDoRequest::new(self);
14568 res.request.do_writeback(
14569 res.protocol(),
14570 "op-dev-get-do-request",
14571 RequestOpDevGetDoRequest::lookup,
14572 );
14573 res
14574 }
14575 pub fn op_page_pool_get_dump_request(self) -> RequestOpPagePoolGetDumpRequest<'buf> {
14576 let mut res = RequestOpPagePoolGetDumpRequest::new(self);
14577 res.request.do_writeback(
14578 res.protocol(),
14579 "op-page-pool-get-dump-request",
14580 RequestOpPagePoolGetDumpRequest::lookup,
14581 );
14582 res
14583 }
14584 pub fn op_page_pool_get_do_request(self) -> RequestOpPagePoolGetDoRequest<'buf> {
14585 let mut res = RequestOpPagePoolGetDoRequest::new(self);
14586 res.request.do_writeback(
14587 res.protocol(),
14588 "op-page-pool-get-do-request",
14589 RequestOpPagePoolGetDoRequest::lookup,
14590 );
14591 res
14592 }
14593 pub fn op_page_pool_stats_get_dump_request(self) -> RequestOpPagePoolStatsGetDumpRequest<'buf> {
14594 let mut res = RequestOpPagePoolStatsGetDumpRequest::new(self);
14595 res.request.do_writeback(
14596 res.protocol(),
14597 "op-page-pool-stats-get-dump-request",
14598 RequestOpPagePoolStatsGetDumpRequest::lookup,
14599 );
14600 res
14601 }
14602 pub fn op_page_pool_stats_get_do_request(self) -> RequestOpPagePoolStatsGetDoRequest<'buf> {
14603 let mut res = RequestOpPagePoolStatsGetDoRequest::new(self);
14604 res.request.do_writeback(
14605 res.protocol(),
14606 "op-page-pool-stats-get-do-request",
14607 RequestOpPagePoolStatsGetDoRequest::lookup,
14608 );
14609 res
14610 }
14611 pub fn op_queue_get_dump_request(self) -> RequestOpQueueGetDumpRequest<'buf> {
14612 let mut res = RequestOpQueueGetDumpRequest::new(self);
14613 res.request.do_writeback(
14614 res.protocol(),
14615 "op-queue-get-dump-request",
14616 RequestOpQueueGetDumpRequest::lookup,
14617 );
14618 res
14619 }
14620 pub fn op_queue_get_do_request(self) -> RequestOpQueueGetDoRequest<'buf> {
14621 let mut res = RequestOpQueueGetDoRequest::new(self);
14622 res.request.do_writeback(
14623 res.protocol(),
14624 "op-queue-get-do-request",
14625 RequestOpQueueGetDoRequest::lookup,
14626 );
14627 res
14628 }
14629 pub fn op_napi_get_dump_request(self) -> RequestOpNapiGetDumpRequest<'buf> {
14630 let mut res = RequestOpNapiGetDumpRequest::new(self);
14631 res.request.do_writeback(
14632 res.protocol(),
14633 "op-napi-get-dump-request",
14634 RequestOpNapiGetDumpRequest::lookup,
14635 );
14636 res
14637 }
14638 pub fn op_napi_get_do_request(self) -> RequestOpNapiGetDoRequest<'buf> {
14639 let mut res = RequestOpNapiGetDoRequest::new(self);
14640 res.request.do_writeback(
14641 res.protocol(),
14642 "op-napi-get-do-request",
14643 RequestOpNapiGetDoRequest::lookup,
14644 );
14645 res
14646 }
14647 pub fn op_qstats_get_dump_request(self) -> RequestOpQstatsGetDumpRequest<'buf> {
14648 let mut res = RequestOpQstatsGetDumpRequest::new(self);
14649 res.request.do_writeback(
14650 res.protocol(),
14651 "op-qstats-get-dump-request",
14652 RequestOpQstatsGetDumpRequest::lookup,
14653 );
14654 res
14655 }
14656 pub fn op_bind_rx_do_request(self) -> RequestOpBindRxDoRequest<'buf> {
14657 let mut res = RequestOpBindRxDoRequest::new(self);
14658 res.request.do_writeback(
14659 res.protocol(),
14660 "op-bind-rx-do-request",
14661 RequestOpBindRxDoRequest::lookup,
14662 );
14663 res
14664 }
14665 pub fn op_napi_set_do_request(self) -> RequestOpNapiSetDoRequest<'buf> {
14666 let mut res = RequestOpNapiSetDoRequest::new(self);
14667 res.request.do_writeback(
14668 res.protocol(),
14669 "op-napi-set-do-request",
14670 RequestOpNapiSetDoRequest::lookup,
14671 );
14672 res
14673 }
14674 pub fn op_bind_tx_do_request(self) -> RequestOpBindTxDoRequest<'buf> {
14675 let mut res = RequestOpBindTxDoRequest::new(self);
14676 res.request.do_writeback(
14677 res.protocol(),
14678 "op-bind-tx-do-request",
14679 RequestOpBindTxDoRequest::lookup,
14680 );
14681 res
14682 }
14683}