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 if self.buf.len() == self.pos {
284 return None;
285 }
286 let pos = self.pos;
287 let mut r#type = None;
288 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
289 r#type = Some(header.r#type);
290 let res = match header.r#type {
291 1u16 => Dev::Ifindex({
292 let res = parse_u32(next);
293 let Some(val) = res else { break };
294 val
295 }),
296 2u16 => Dev::Pad({
297 let res = Some(next);
298 let Some(val) = res else { break };
299 val
300 }),
301 3u16 => Dev::XdpFeatures({
302 let res = parse_u64(next);
303 let Some(val) = res else { break };
304 val
305 }),
306 4u16 => Dev::XdpZcMaxSegs({
307 let res = parse_u32(next);
308 let Some(val) = res else { break };
309 val
310 }),
311 5u16 => Dev::XdpRxMetadataFeatures({
312 let res = parse_u64(next);
313 let Some(val) = res else { break };
314 val
315 }),
316 6u16 => Dev::XskFeatures({
317 let res = parse_u64(next);
318 let Some(val) = res else { break };
319 val
320 }),
321 n => {
322 if cfg!(any(test, feature = "deny-unknown-attrs")) {
323 break;
324 } else {
325 continue;
326 }
327 }
328 };
329 return Some(Ok(res));
330 }
331 Some(Err(ErrorContext::new(
332 "Dev",
333 r#type.and_then(|t| Dev::attr_from_type(t)),
334 self.orig_loc,
335 self.buf.as_ptr().wrapping_add(pos) as usize,
336 )))
337 }
338}
339impl<'a> std::fmt::Debug for IterableDev<'_> {
340 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
341 let mut fmt = f.debug_struct("Dev");
342 for attr in self.clone() {
343 let attr = match attr {
344 Ok(a) => a,
345 Err(err) => {
346 fmt.finish()?;
347 f.write_str("Err(")?;
348 err.fmt(f)?;
349 return f.write_str(")");
350 }
351 };
352 match attr {
353 Dev::Ifindex(val) => fmt.field("Ifindex", &val),
354 Dev::Pad(val) => fmt.field("Pad", &val),
355 Dev::XdpFeatures(val) => {
356 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
357 }
358 Dev::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
359 Dev::XdpRxMetadataFeatures(val) => fmt.field(
360 "XdpRxMetadataFeatures",
361 &FormatFlags(val.into(), XdpRxMetadata::from_value),
362 ),
363 Dev::XskFeatures(val) => fmt.field(
364 "XskFeatures",
365 &FormatFlags(val.into(), XskFlags::from_value),
366 ),
367 };
368 }
369 fmt.finish()
370 }
371}
372impl IterableDev<'_> {
373 pub fn lookup_attr(
374 &self,
375 offset: usize,
376 missing_type: Option<u16>,
377 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
378 let mut stack = Vec::new();
379 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
380 if cur == offset {
381 stack.push(("Dev", offset));
382 return (stack, missing_type.and_then(|t| Dev::attr_from_type(t)));
383 }
384 if cur > offset || cur + self.buf.len() < offset {
385 return (stack, None);
386 }
387 let mut attrs = self.clone();
388 let mut last_off = cur + attrs.pos;
389 while let Some(attr) = attrs.next() {
390 let Ok(attr) = attr else { break };
391 match attr {
392 Dev::Ifindex(val) => {
393 if last_off == offset {
394 stack.push(("Ifindex", last_off));
395 break;
396 }
397 }
398 Dev::Pad(val) => {
399 if last_off == offset {
400 stack.push(("Pad", last_off));
401 break;
402 }
403 }
404 Dev::XdpFeatures(val) => {
405 if last_off == offset {
406 stack.push(("XdpFeatures", last_off));
407 break;
408 }
409 }
410 Dev::XdpZcMaxSegs(val) => {
411 if last_off == offset {
412 stack.push(("XdpZcMaxSegs", last_off));
413 break;
414 }
415 }
416 Dev::XdpRxMetadataFeatures(val) => {
417 if last_off == offset {
418 stack.push(("XdpRxMetadataFeatures", last_off));
419 break;
420 }
421 }
422 Dev::XskFeatures(val) => {
423 if last_off == offset {
424 stack.push(("XskFeatures", last_off));
425 break;
426 }
427 }
428 _ => {}
429 };
430 last_off = cur + attrs.pos;
431 }
432 if !stack.is_empty() {
433 stack.push(("Dev", cur));
434 }
435 (stack, None)
436 }
437}
438#[derive(Clone)]
439pub enum IoUringProviderInfo {}
440impl<'a> IterableIoUringProviderInfo<'a> {}
441impl IoUringProviderInfo {
442 pub fn new<'a>(buf: &'a [u8]) -> IterableIoUringProviderInfo<'a> {
443 IterableIoUringProviderInfo::with_loc(buf, buf.as_ptr() as usize)
444 }
445 fn attr_from_type(r#type: u16) -> Option<&'static str> {
446 None
447 }
448}
449#[derive(Clone, Copy, Default)]
450pub struct IterableIoUringProviderInfo<'a> {
451 buf: &'a [u8],
452 pos: usize,
453 orig_loc: usize,
454}
455impl<'a> IterableIoUringProviderInfo<'a> {
456 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
457 Self {
458 buf,
459 pos: 0,
460 orig_loc,
461 }
462 }
463 pub fn get_buf(&self) -> &'a [u8] {
464 self.buf
465 }
466}
467impl<'a> Iterator for IterableIoUringProviderInfo<'a> {
468 type Item = Result<IoUringProviderInfo, ErrorContext>;
469 fn next(&mut self) -> Option<Self::Item> {
470 if self.buf.len() == self.pos {
471 return None;
472 }
473 let pos = self.pos;
474 let mut r#type = None;
475 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
476 r#type = Some(header.r#type);
477 let res = match header.r#type {
478 n => {
479 if cfg!(any(test, feature = "deny-unknown-attrs")) {
480 break;
481 } else {
482 continue;
483 }
484 }
485 };
486 return Some(Ok(res));
487 }
488 Some(Err(ErrorContext::new(
489 "IoUringProviderInfo",
490 r#type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
491 self.orig_loc,
492 self.buf.as_ptr().wrapping_add(pos) as usize,
493 )))
494 }
495}
496impl std::fmt::Debug for IterableIoUringProviderInfo<'_> {
497 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
498 let mut fmt = f.debug_struct("IoUringProviderInfo");
499 for attr in self.clone() {
500 let attr = match attr {
501 Ok(a) => a,
502 Err(err) => {
503 fmt.finish()?;
504 f.write_str("Err(")?;
505 err.fmt(f)?;
506 return f.write_str(")");
507 }
508 };
509 match attr {};
510 }
511 fmt.finish()
512 }
513}
514impl IterableIoUringProviderInfo<'_> {
515 pub fn lookup_attr(
516 &self,
517 offset: usize,
518 missing_type: Option<u16>,
519 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
520 let mut stack = Vec::new();
521 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
522 if cur == offset {
523 stack.push(("IoUringProviderInfo", offset));
524 return (
525 stack,
526 missing_type.and_then(|t| IoUringProviderInfo::attr_from_type(t)),
527 );
528 }
529 (stack, None)
530 }
531}
532#[derive(Clone)]
533pub enum PagePool<'a> {
534 #[doc = "Unique ID of a Page Pool instance."]
535 Id(u32),
536 #[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"]
537 Ifindex(u32),
538 #[doc = "Id of NAPI using this Page Pool instance."]
539 NapiId(u32),
540 #[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"]
541 Inflight(u32),
542 #[doc = "Amount of memory held by inflight pages.\n"]
543 InflightMem(u32),
544 #[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"]
545 DetachTime(u32),
546 #[doc = "ID of the dmabuf this page-pool is attached to."]
547 Dmabuf(u32),
548 #[doc = "io-uring memory provider information."]
549 IoUring(IterableIoUringProviderInfo<'a>),
550}
551impl<'a> IterablePagePool<'a> {
552 #[doc = "Unique ID of a Page Pool instance."]
553 pub fn get_id(&self) -> Result<u32, ErrorContext> {
554 let mut iter = self.clone();
555 iter.pos = 0;
556 for attr in iter {
557 if let PagePool::Id(val) = attr? {
558 return Ok(val);
559 }
560 }
561 Err(ErrorContext::new_missing(
562 "PagePool",
563 "Id",
564 self.orig_loc,
565 self.buf.as_ptr() as usize,
566 ))
567 }
568 #[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"]
569 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
570 let mut iter = self.clone();
571 iter.pos = 0;
572 for attr in iter {
573 if let PagePool::Ifindex(val) = attr? {
574 return Ok(val);
575 }
576 }
577 Err(ErrorContext::new_missing(
578 "PagePool",
579 "Ifindex",
580 self.orig_loc,
581 self.buf.as_ptr() as usize,
582 ))
583 }
584 #[doc = "Id of NAPI using this Page Pool instance."]
585 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
586 let mut iter = self.clone();
587 iter.pos = 0;
588 for attr in iter {
589 if let PagePool::NapiId(val) = attr? {
590 return Ok(val);
591 }
592 }
593 Err(ErrorContext::new_missing(
594 "PagePool",
595 "NapiId",
596 self.orig_loc,
597 self.buf.as_ptr() as usize,
598 ))
599 }
600 #[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"]
601 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
602 let mut iter = self.clone();
603 iter.pos = 0;
604 for attr in iter {
605 if let PagePool::Inflight(val) = attr? {
606 return Ok(val);
607 }
608 }
609 Err(ErrorContext::new_missing(
610 "PagePool",
611 "Inflight",
612 self.orig_loc,
613 self.buf.as_ptr() as usize,
614 ))
615 }
616 #[doc = "Amount of memory held by inflight pages.\n"]
617 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
618 let mut iter = self.clone();
619 iter.pos = 0;
620 for attr in iter {
621 if let PagePool::InflightMem(val) = attr? {
622 return Ok(val);
623 }
624 }
625 Err(ErrorContext::new_missing(
626 "PagePool",
627 "InflightMem",
628 self.orig_loc,
629 self.buf.as_ptr() as usize,
630 ))
631 }
632 #[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"]
633 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
634 let mut iter = self.clone();
635 iter.pos = 0;
636 for attr in iter {
637 if let PagePool::DetachTime(val) = attr? {
638 return Ok(val);
639 }
640 }
641 Err(ErrorContext::new_missing(
642 "PagePool",
643 "DetachTime",
644 self.orig_loc,
645 self.buf.as_ptr() as usize,
646 ))
647 }
648 #[doc = "ID of the dmabuf this page-pool is attached to."]
649 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
650 let mut iter = self.clone();
651 iter.pos = 0;
652 for attr in iter {
653 if let PagePool::Dmabuf(val) = attr? {
654 return Ok(val);
655 }
656 }
657 Err(ErrorContext::new_missing(
658 "PagePool",
659 "Dmabuf",
660 self.orig_loc,
661 self.buf.as_ptr() as usize,
662 ))
663 }
664 #[doc = "io-uring memory provider information."]
665 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
666 let mut iter = self.clone();
667 iter.pos = 0;
668 for attr in iter {
669 if let PagePool::IoUring(val) = attr? {
670 return Ok(val);
671 }
672 }
673 Err(ErrorContext::new_missing(
674 "PagePool",
675 "IoUring",
676 self.orig_loc,
677 self.buf.as_ptr() as usize,
678 ))
679 }
680}
681impl PagePool<'_> {
682 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePool<'a> {
683 IterablePagePool::with_loc(buf, buf.as_ptr() as usize)
684 }
685 fn attr_from_type(r#type: u16) -> Option<&'static str> {
686 let res = match r#type {
687 1u16 => "Id",
688 2u16 => "Ifindex",
689 3u16 => "NapiId",
690 4u16 => "Inflight",
691 5u16 => "InflightMem",
692 6u16 => "DetachTime",
693 7u16 => "Dmabuf",
694 8u16 => "IoUring",
695 _ => return None,
696 };
697 Some(res)
698 }
699}
700#[derive(Clone, Copy, Default)]
701pub struct IterablePagePool<'a> {
702 buf: &'a [u8],
703 pos: usize,
704 orig_loc: usize,
705}
706impl<'a> IterablePagePool<'a> {
707 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
708 Self {
709 buf,
710 pos: 0,
711 orig_loc,
712 }
713 }
714 pub fn get_buf(&self) -> &'a [u8] {
715 self.buf
716 }
717}
718impl<'a> Iterator for IterablePagePool<'a> {
719 type Item = Result<PagePool<'a>, ErrorContext>;
720 fn next(&mut self) -> Option<Self::Item> {
721 if self.buf.len() == self.pos {
722 return None;
723 }
724 let pos = self.pos;
725 let mut r#type = None;
726 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
727 r#type = Some(header.r#type);
728 let res = match header.r#type {
729 1u16 => PagePool::Id({
730 let res = parse_u32(next);
731 let Some(val) = res else { break };
732 val
733 }),
734 2u16 => PagePool::Ifindex({
735 let res = parse_u32(next);
736 let Some(val) = res else { break };
737 val
738 }),
739 3u16 => PagePool::NapiId({
740 let res = parse_u32(next);
741 let Some(val) = res else { break };
742 val
743 }),
744 4u16 => PagePool::Inflight({
745 let res = parse_u32(next);
746 let Some(val) = res else { break };
747 val
748 }),
749 5u16 => PagePool::InflightMem({
750 let res = parse_u32(next);
751 let Some(val) = res else { break };
752 val
753 }),
754 6u16 => PagePool::DetachTime({
755 let res = parse_u32(next);
756 let Some(val) = res else { break };
757 val
758 }),
759 7u16 => PagePool::Dmabuf({
760 let res = parse_u32(next);
761 let Some(val) = res else { break };
762 val
763 }),
764 8u16 => PagePool::IoUring({
765 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
766 let Some(val) = res else { break };
767 val
768 }),
769 n => {
770 if cfg!(any(test, feature = "deny-unknown-attrs")) {
771 break;
772 } else {
773 continue;
774 }
775 }
776 };
777 return Some(Ok(res));
778 }
779 Some(Err(ErrorContext::new(
780 "PagePool",
781 r#type.and_then(|t| PagePool::attr_from_type(t)),
782 self.orig_loc,
783 self.buf.as_ptr().wrapping_add(pos) as usize,
784 )))
785 }
786}
787impl<'a> std::fmt::Debug for IterablePagePool<'_> {
788 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
789 let mut fmt = f.debug_struct("PagePool");
790 for attr in self.clone() {
791 let attr = match attr {
792 Ok(a) => a,
793 Err(err) => {
794 fmt.finish()?;
795 f.write_str("Err(")?;
796 err.fmt(f)?;
797 return f.write_str(")");
798 }
799 };
800 match attr {
801 PagePool::Id(val) => fmt.field("Id", &val),
802 PagePool::Ifindex(val) => fmt.field("Ifindex", &val),
803 PagePool::NapiId(val) => fmt.field("NapiId", &val),
804 PagePool::Inflight(val) => fmt.field("Inflight", &val),
805 PagePool::InflightMem(val) => fmt.field("InflightMem", &val),
806 PagePool::DetachTime(val) => fmt.field("DetachTime", &val),
807 PagePool::Dmabuf(val) => fmt.field("Dmabuf", &val),
808 PagePool::IoUring(val) => fmt.field("IoUring", &val),
809 };
810 }
811 fmt.finish()
812 }
813}
814impl IterablePagePool<'_> {
815 pub fn lookup_attr(
816 &self,
817 offset: usize,
818 missing_type: Option<u16>,
819 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
820 let mut stack = Vec::new();
821 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
822 if cur == offset {
823 stack.push(("PagePool", offset));
824 return (
825 stack,
826 missing_type.and_then(|t| PagePool::attr_from_type(t)),
827 );
828 }
829 if cur > offset || cur + self.buf.len() < offset {
830 return (stack, None);
831 }
832 let mut attrs = self.clone();
833 let mut last_off = cur + attrs.pos;
834 let mut missing = None;
835 while let Some(attr) = attrs.next() {
836 let Ok(attr) = attr else { break };
837 match attr {
838 PagePool::Id(val) => {
839 if last_off == offset {
840 stack.push(("Id", last_off));
841 break;
842 }
843 }
844 PagePool::Ifindex(val) => {
845 if last_off == offset {
846 stack.push(("Ifindex", last_off));
847 break;
848 }
849 }
850 PagePool::NapiId(val) => {
851 if last_off == offset {
852 stack.push(("NapiId", last_off));
853 break;
854 }
855 }
856 PagePool::Inflight(val) => {
857 if last_off == offset {
858 stack.push(("Inflight", last_off));
859 break;
860 }
861 }
862 PagePool::InflightMem(val) => {
863 if last_off == offset {
864 stack.push(("InflightMem", last_off));
865 break;
866 }
867 }
868 PagePool::DetachTime(val) => {
869 if last_off == offset {
870 stack.push(("DetachTime", last_off));
871 break;
872 }
873 }
874 PagePool::Dmabuf(val) => {
875 if last_off == offset {
876 stack.push(("Dmabuf", last_off));
877 break;
878 }
879 }
880 PagePool::IoUring(val) => {
881 (stack, missing) = val.lookup_attr(offset, missing_type);
882 if !stack.is_empty() {
883 break;
884 }
885 }
886 _ => {}
887 };
888 last_off = cur + attrs.pos;
889 }
890 if !stack.is_empty() {
891 stack.push(("PagePool", cur));
892 }
893 (stack, missing)
894 }
895}
896#[derive(Clone)]
897pub enum PagePoolInfo {
898 #[doc = "Unique ID of a Page Pool instance."]
899 Id(u32),
900 #[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"]
901 Ifindex(u32),
902}
903impl<'a> IterablePagePoolInfo<'a> {
904 #[doc = "Unique ID of a Page Pool instance."]
905 pub fn get_id(&self) -> Result<u32, ErrorContext> {
906 let mut iter = self.clone();
907 iter.pos = 0;
908 for attr in iter {
909 if let PagePoolInfo::Id(val) = attr? {
910 return Ok(val);
911 }
912 }
913 Err(ErrorContext::new_missing(
914 "PagePoolInfo",
915 "Id",
916 self.orig_loc,
917 self.buf.as_ptr() as usize,
918 ))
919 }
920 #[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"]
921 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
922 let mut iter = self.clone();
923 iter.pos = 0;
924 for attr in iter {
925 if let PagePoolInfo::Ifindex(val) = attr? {
926 return Ok(val);
927 }
928 }
929 Err(ErrorContext::new_missing(
930 "PagePoolInfo",
931 "Ifindex",
932 self.orig_loc,
933 self.buf.as_ptr() as usize,
934 ))
935 }
936}
937impl PagePoolInfo {
938 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolInfo<'a> {
939 IterablePagePoolInfo::with_loc(buf, buf.as_ptr() as usize)
940 }
941 fn attr_from_type(r#type: u16) -> Option<&'static str> {
942 PagePool::attr_from_type(r#type)
943 }
944}
945#[derive(Clone, Copy, Default)]
946pub struct IterablePagePoolInfo<'a> {
947 buf: &'a [u8],
948 pos: usize,
949 orig_loc: usize,
950}
951impl<'a> IterablePagePoolInfo<'a> {
952 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
953 Self {
954 buf,
955 pos: 0,
956 orig_loc,
957 }
958 }
959 pub fn get_buf(&self) -> &'a [u8] {
960 self.buf
961 }
962}
963impl<'a> Iterator for IterablePagePoolInfo<'a> {
964 type Item = Result<PagePoolInfo, ErrorContext>;
965 fn next(&mut self) -> Option<Self::Item> {
966 if self.buf.len() == self.pos {
967 return None;
968 }
969 let pos = self.pos;
970 let mut r#type = None;
971 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
972 r#type = Some(header.r#type);
973 let res = match header.r#type {
974 1u16 => PagePoolInfo::Id({
975 let res = parse_u32(next);
976 let Some(val) = res else { break };
977 val
978 }),
979 2u16 => PagePoolInfo::Ifindex({
980 let res = parse_u32(next);
981 let Some(val) = res else { break };
982 val
983 }),
984 n => {
985 if cfg!(any(test, feature = "deny-unknown-attrs")) {
986 break;
987 } else {
988 continue;
989 }
990 }
991 };
992 return Some(Ok(res));
993 }
994 Some(Err(ErrorContext::new(
995 "PagePoolInfo",
996 r#type.and_then(|t| PagePoolInfo::attr_from_type(t)),
997 self.orig_loc,
998 self.buf.as_ptr().wrapping_add(pos) as usize,
999 )))
1000 }
1001}
1002impl std::fmt::Debug for IterablePagePoolInfo<'_> {
1003 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1004 let mut fmt = f.debug_struct("PagePoolInfo");
1005 for attr in self.clone() {
1006 let attr = match attr {
1007 Ok(a) => a,
1008 Err(err) => {
1009 fmt.finish()?;
1010 f.write_str("Err(")?;
1011 err.fmt(f)?;
1012 return f.write_str(")");
1013 }
1014 };
1015 match attr {
1016 PagePoolInfo::Id(val) => fmt.field("Id", &val),
1017 PagePoolInfo::Ifindex(val) => fmt.field("Ifindex", &val),
1018 };
1019 }
1020 fmt.finish()
1021 }
1022}
1023impl IterablePagePoolInfo<'_> {
1024 pub fn lookup_attr(
1025 &self,
1026 offset: usize,
1027 missing_type: Option<u16>,
1028 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1029 let mut stack = Vec::new();
1030 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1031 if cur == offset {
1032 stack.push(("PagePoolInfo", offset));
1033 return (
1034 stack,
1035 missing_type.and_then(|t| PagePoolInfo::attr_from_type(t)),
1036 );
1037 }
1038 if cur > offset || cur + self.buf.len() < offset {
1039 return (stack, None);
1040 }
1041 let mut attrs = self.clone();
1042 let mut last_off = cur + attrs.pos;
1043 while let Some(attr) = attrs.next() {
1044 let Ok(attr) = attr else { break };
1045 match attr {
1046 PagePoolInfo::Id(val) => {
1047 if last_off == offset {
1048 stack.push(("Id", last_off));
1049 break;
1050 }
1051 }
1052 PagePoolInfo::Ifindex(val) => {
1053 if last_off == offset {
1054 stack.push(("Ifindex", last_off));
1055 break;
1056 }
1057 }
1058 _ => {}
1059 };
1060 last_off = cur + attrs.pos;
1061 }
1062 if !stack.is_empty() {
1063 stack.push(("PagePoolInfo", cur));
1064 }
1065 (stack, None)
1066 }
1067}
1068#[derive(Clone)]
1069pub enum PagePoolStats<'a> {
1070 #[doc = "Page pool identifying information."]
1071 Info(IterablePagePoolInfo<'a>),
1072 AllocFast(u32),
1073 AllocSlow(u32),
1074 AllocSlowHighOrder(u32),
1075 AllocEmpty(u32),
1076 AllocRefill(u32),
1077 AllocWaive(u32),
1078 RecycleCached(u32),
1079 RecycleCacheFull(u32),
1080 RecycleRing(u32),
1081 RecycleRingFull(u32),
1082 RecycleReleasedRefcnt(u32),
1083}
1084impl<'a> IterablePagePoolStats<'a> {
1085 #[doc = "Page pool identifying information."]
1086 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
1087 let mut iter = self.clone();
1088 iter.pos = 0;
1089 for attr in iter {
1090 if let PagePoolStats::Info(val) = attr? {
1091 return Ok(val);
1092 }
1093 }
1094 Err(ErrorContext::new_missing(
1095 "PagePoolStats",
1096 "Info",
1097 self.orig_loc,
1098 self.buf.as_ptr() as usize,
1099 ))
1100 }
1101 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
1102 let mut iter = self.clone();
1103 iter.pos = 0;
1104 for attr in iter {
1105 if let PagePoolStats::AllocFast(val) = attr? {
1106 return Ok(val);
1107 }
1108 }
1109 Err(ErrorContext::new_missing(
1110 "PagePoolStats",
1111 "AllocFast",
1112 self.orig_loc,
1113 self.buf.as_ptr() as usize,
1114 ))
1115 }
1116 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
1117 let mut iter = self.clone();
1118 iter.pos = 0;
1119 for attr in iter {
1120 if let PagePoolStats::AllocSlow(val) = attr? {
1121 return Ok(val);
1122 }
1123 }
1124 Err(ErrorContext::new_missing(
1125 "PagePoolStats",
1126 "AllocSlow",
1127 self.orig_loc,
1128 self.buf.as_ptr() as usize,
1129 ))
1130 }
1131 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
1132 let mut iter = self.clone();
1133 iter.pos = 0;
1134 for attr in iter {
1135 if let PagePoolStats::AllocSlowHighOrder(val) = attr? {
1136 return Ok(val);
1137 }
1138 }
1139 Err(ErrorContext::new_missing(
1140 "PagePoolStats",
1141 "AllocSlowHighOrder",
1142 self.orig_loc,
1143 self.buf.as_ptr() as usize,
1144 ))
1145 }
1146 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
1147 let mut iter = self.clone();
1148 iter.pos = 0;
1149 for attr in iter {
1150 if let PagePoolStats::AllocEmpty(val) = attr? {
1151 return Ok(val);
1152 }
1153 }
1154 Err(ErrorContext::new_missing(
1155 "PagePoolStats",
1156 "AllocEmpty",
1157 self.orig_loc,
1158 self.buf.as_ptr() as usize,
1159 ))
1160 }
1161 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
1162 let mut iter = self.clone();
1163 iter.pos = 0;
1164 for attr in iter {
1165 if let PagePoolStats::AllocRefill(val) = attr? {
1166 return Ok(val);
1167 }
1168 }
1169 Err(ErrorContext::new_missing(
1170 "PagePoolStats",
1171 "AllocRefill",
1172 self.orig_loc,
1173 self.buf.as_ptr() as usize,
1174 ))
1175 }
1176 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
1177 let mut iter = self.clone();
1178 iter.pos = 0;
1179 for attr in iter {
1180 if let PagePoolStats::AllocWaive(val) = attr? {
1181 return Ok(val);
1182 }
1183 }
1184 Err(ErrorContext::new_missing(
1185 "PagePoolStats",
1186 "AllocWaive",
1187 self.orig_loc,
1188 self.buf.as_ptr() as usize,
1189 ))
1190 }
1191 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
1192 let mut iter = self.clone();
1193 iter.pos = 0;
1194 for attr in iter {
1195 if let PagePoolStats::RecycleCached(val) = attr? {
1196 return Ok(val);
1197 }
1198 }
1199 Err(ErrorContext::new_missing(
1200 "PagePoolStats",
1201 "RecycleCached",
1202 self.orig_loc,
1203 self.buf.as_ptr() as usize,
1204 ))
1205 }
1206 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
1207 let mut iter = self.clone();
1208 iter.pos = 0;
1209 for attr in iter {
1210 if let PagePoolStats::RecycleCacheFull(val) = attr? {
1211 return Ok(val);
1212 }
1213 }
1214 Err(ErrorContext::new_missing(
1215 "PagePoolStats",
1216 "RecycleCacheFull",
1217 self.orig_loc,
1218 self.buf.as_ptr() as usize,
1219 ))
1220 }
1221 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
1222 let mut iter = self.clone();
1223 iter.pos = 0;
1224 for attr in iter {
1225 if let PagePoolStats::RecycleRing(val) = attr? {
1226 return Ok(val);
1227 }
1228 }
1229 Err(ErrorContext::new_missing(
1230 "PagePoolStats",
1231 "RecycleRing",
1232 self.orig_loc,
1233 self.buf.as_ptr() as usize,
1234 ))
1235 }
1236 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
1237 let mut iter = self.clone();
1238 iter.pos = 0;
1239 for attr in iter {
1240 if let PagePoolStats::RecycleRingFull(val) = attr? {
1241 return Ok(val);
1242 }
1243 }
1244 Err(ErrorContext::new_missing(
1245 "PagePoolStats",
1246 "RecycleRingFull",
1247 self.orig_loc,
1248 self.buf.as_ptr() as usize,
1249 ))
1250 }
1251 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
1252 let mut iter = self.clone();
1253 iter.pos = 0;
1254 for attr in iter {
1255 if let PagePoolStats::RecycleReleasedRefcnt(val) = attr? {
1256 return Ok(val);
1257 }
1258 }
1259 Err(ErrorContext::new_missing(
1260 "PagePoolStats",
1261 "RecycleReleasedRefcnt",
1262 self.orig_loc,
1263 self.buf.as_ptr() as usize,
1264 ))
1265 }
1266}
1267impl PagePoolStats<'_> {
1268 pub fn new<'a>(buf: &'a [u8]) -> IterablePagePoolStats<'a> {
1269 IterablePagePoolStats::with_loc(buf, buf.as_ptr() as usize)
1270 }
1271 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1272 let res = match r#type {
1273 1u16 => "Info",
1274 8u16 => "AllocFast",
1275 9u16 => "AllocSlow",
1276 10u16 => "AllocSlowHighOrder",
1277 11u16 => "AllocEmpty",
1278 12u16 => "AllocRefill",
1279 13u16 => "AllocWaive",
1280 14u16 => "RecycleCached",
1281 15u16 => "RecycleCacheFull",
1282 16u16 => "RecycleRing",
1283 17u16 => "RecycleRingFull",
1284 18u16 => "RecycleReleasedRefcnt",
1285 _ => return None,
1286 };
1287 Some(res)
1288 }
1289}
1290#[derive(Clone, Copy, Default)]
1291pub struct IterablePagePoolStats<'a> {
1292 buf: &'a [u8],
1293 pos: usize,
1294 orig_loc: usize,
1295}
1296impl<'a> IterablePagePoolStats<'a> {
1297 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1298 Self {
1299 buf,
1300 pos: 0,
1301 orig_loc,
1302 }
1303 }
1304 pub fn get_buf(&self) -> &'a [u8] {
1305 self.buf
1306 }
1307}
1308impl<'a> Iterator for IterablePagePoolStats<'a> {
1309 type Item = Result<PagePoolStats<'a>, ErrorContext>;
1310 fn next(&mut self) -> Option<Self::Item> {
1311 if self.buf.len() == self.pos {
1312 return None;
1313 }
1314 let pos = self.pos;
1315 let mut r#type = None;
1316 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
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 => {
1380 if cfg!(any(test, feature = "deny-unknown-attrs")) {
1381 break;
1382 } else {
1383 continue;
1384 }
1385 }
1386 };
1387 return Some(Ok(res));
1388 }
1389 Some(Err(ErrorContext::new(
1390 "PagePoolStats",
1391 r#type.and_then(|t| PagePoolStats::attr_from_type(t)),
1392 self.orig_loc,
1393 self.buf.as_ptr().wrapping_add(pos) as usize,
1394 )))
1395 }
1396}
1397impl<'a> std::fmt::Debug for IterablePagePoolStats<'_> {
1398 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1399 let mut fmt = f.debug_struct("PagePoolStats");
1400 for attr in self.clone() {
1401 let attr = match attr {
1402 Ok(a) => a,
1403 Err(err) => {
1404 fmt.finish()?;
1405 f.write_str("Err(")?;
1406 err.fmt(f)?;
1407 return f.write_str(")");
1408 }
1409 };
1410 match attr {
1411 PagePoolStats::Info(val) => fmt.field("Info", &val),
1412 PagePoolStats::AllocFast(val) => fmt.field("AllocFast", &val),
1413 PagePoolStats::AllocSlow(val) => fmt.field("AllocSlow", &val),
1414 PagePoolStats::AllocSlowHighOrder(val) => fmt.field("AllocSlowHighOrder", &val),
1415 PagePoolStats::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
1416 PagePoolStats::AllocRefill(val) => fmt.field("AllocRefill", &val),
1417 PagePoolStats::AllocWaive(val) => fmt.field("AllocWaive", &val),
1418 PagePoolStats::RecycleCached(val) => fmt.field("RecycleCached", &val),
1419 PagePoolStats::RecycleCacheFull(val) => fmt.field("RecycleCacheFull", &val),
1420 PagePoolStats::RecycleRing(val) => fmt.field("RecycleRing", &val),
1421 PagePoolStats::RecycleRingFull(val) => fmt.field("RecycleRingFull", &val),
1422 PagePoolStats::RecycleReleasedRefcnt(val) => {
1423 fmt.field("RecycleReleasedRefcnt", &val)
1424 }
1425 };
1426 }
1427 fmt.finish()
1428 }
1429}
1430impl IterablePagePoolStats<'_> {
1431 pub fn lookup_attr(
1432 &self,
1433 offset: usize,
1434 missing_type: Option<u16>,
1435 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1436 let mut stack = Vec::new();
1437 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1438 if cur == offset {
1439 stack.push(("PagePoolStats", offset));
1440 return (
1441 stack,
1442 missing_type.and_then(|t| PagePoolStats::attr_from_type(t)),
1443 );
1444 }
1445 if cur > offset || cur + self.buf.len() < offset {
1446 return (stack, None);
1447 }
1448 let mut attrs = self.clone();
1449 let mut last_off = cur + attrs.pos;
1450 let mut missing = None;
1451 while let Some(attr) = attrs.next() {
1452 let Ok(attr) = attr else { break };
1453 match attr {
1454 PagePoolStats::Info(val) => {
1455 (stack, missing) = val.lookup_attr(offset, missing_type);
1456 if !stack.is_empty() {
1457 break;
1458 }
1459 }
1460 PagePoolStats::AllocFast(val) => {
1461 if last_off == offset {
1462 stack.push(("AllocFast", last_off));
1463 break;
1464 }
1465 }
1466 PagePoolStats::AllocSlow(val) => {
1467 if last_off == offset {
1468 stack.push(("AllocSlow", last_off));
1469 break;
1470 }
1471 }
1472 PagePoolStats::AllocSlowHighOrder(val) => {
1473 if last_off == offset {
1474 stack.push(("AllocSlowHighOrder", last_off));
1475 break;
1476 }
1477 }
1478 PagePoolStats::AllocEmpty(val) => {
1479 if last_off == offset {
1480 stack.push(("AllocEmpty", last_off));
1481 break;
1482 }
1483 }
1484 PagePoolStats::AllocRefill(val) => {
1485 if last_off == offset {
1486 stack.push(("AllocRefill", last_off));
1487 break;
1488 }
1489 }
1490 PagePoolStats::AllocWaive(val) => {
1491 if last_off == offset {
1492 stack.push(("AllocWaive", last_off));
1493 break;
1494 }
1495 }
1496 PagePoolStats::RecycleCached(val) => {
1497 if last_off == offset {
1498 stack.push(("RecycleCached", last_off));
1499 break;
1500 }
1501 }
1502 PagePoolStats::RecycleCacheFull(val) => {
1503 if last_off == offset {
1504 stack.push(("RecycleCacheFull", last_off));
1505 break;
1506 }
1507 }
1508 PagePoolStats::RecycleRing(val) => {
1509 if last_off == offset {
1510 stack.push(("RecycleRing", last_off));
1511 break;
1512 }
1513 }
1514 PagePoolStats::RecycleRingFull(val) => {
1515 if last_off == offset {
1516 stack.push(("RecycleRingFull", last_off));
1517 break;
1518 }
1519 }
1520 PagePoolStats::RecycleReleasedRefcnt(val) => {
1521 if last_off == offset {
1522 stack.push(("RecycleReleasedRefcnt", last_off));
1523 break;
1524 }
1525 }
1526 _ => {}
1527 };
1528 last_off = cur + attrs.pos;
1529 }
1530 if !stack.is_empty() {
1531 stack.push(("PagePoolStats", cur));
1532 }
1533 (stack, missing)
1534 }
1535}
1536#[derive(Clone)]
1537pub enum Napi {
1538 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1539 Ifindex(u32),
1540 #[doc = "ID of the NAPI instance."]
1541 Id(u32),
1542 #[doc = "The associated interrupt vector number for the napi"]
1543 Irq(u32),
1544 #[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."]
1545 Pid(u32),
1546 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1547 DeferHardIrqs(u32),
1548 #[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."]
1549 GroFlushTimeout(u32),
1550 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1551 IrqSuspendTimeout(u32),
1552 #[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)"]
1553 Threaded(u32),
1554}
1555impl<'a> IterableNapi<'a> {
1556 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
1557 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
1558 let mut iter = self.clone();
1559 iter.pos = 0;
1560 for attr in iter {
1561 if let Napi::Ifindex(val) = attr? {
1562 return Ok(val);
1563 }
1564 }
1565 Err(ErrorContext::new_missing(
1566 "Napi",
1567 "Ifindex",
1568 self.orig_loc,
1569 self.buf.as_ptr() as usize,
1570 ))
1571 }
1572 #[doc = "ID of the NAPI instance."]
1573 pub fn get_id(&self) -> Result<u32, ErrorContext> {
1574 let mut iter = self.clone();
1575 iter.pos = 0;
1576 for attr in iter {
1577 if let Napi::Id(val) = attr? {
1578 return Ok(val);
1579 }
1580 }
1581 Err(ErrorContext::new_missing(
1582 "Napi",
1583 "Id",
1584 self.orig_loc,
1585 self.buf.as_ptr() as usize,
1586 ))
1587 }
1588 #[doc = "The associated interrupt vector number for the napi"]
1589 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
1590 let mut iter = self.clone();
1591 iter.pos = 0;
1592 for attr in iter {
1593 if let Napi::Irq(val) = attr? {
1594 return Ok(val);
1595 }
1596 }
1597 Err(ErrorContext::new_missing(
1598 "Napi",
1599 "Irq",
1600 self.orig_loc,
1601 self.buf.as_ptr() as usize,
1602 ))
1603 }
1604 #[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."]
1605 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
1606 let mut iter = self.clone();
1607 iter.pos = 0;
1608 for attr in iter {
1609 if let Napi::Pid(val) = attr? {
1610 return Ok(val);
1611 }
1612 }
1613 Err(ErrorContext::new_missing(
1614 "Napi",
1615 "Pid",
1616 self.orig_loc,
1617 self.buf.as_ptr() as usize,
1618 ))
1619 }
1620 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
1621 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
1622 let mut iter = self.clone();
1623 iter.pos = 0;
1624 for attr in iter {
1625 if let Napi::DeferHardIrqs(val) = attr? {
1626 return Ok(val);
1627 }
1628 }
1629 Err(ErrorContext::new_missing(
1630 "Napi",
1631 "DeferHardIrqs",
1632 self.orig_loc,
1633 self.buf.as_ptr() as usize,
1634 ))
1635 }
1636 #[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."]
1637 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
1638 let mut iter = self.clone();
1639 iter.pos = 0;
1640 for attr in iter {
1641 if let Napi::GroFlushTimeout(val) = attr? {
1642 return Ok(val);
1643 }
1644 }
1645 Err(ErrorContext::new_missing(
1646 "Napi",
1647 "GroFlushTimeout",
1648 self.orig_loc,
1649 self.buf.as_ptr() as usize,
1650 ))
1651 }
1652 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
1653 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
1654 let mut iter = self.clone();
1655 iter.pos = 0;
1656 for attr in iter {
1657 if let Napi::IrqSuspendTimeout(val) = attr? {
1658 return Ok(val);
1659 }
1660 }
1661 Err(ErrorContext::new_missing(
1662 "Napi",
1663 "IrqSuspendTimeout",
1664 self.orig_loc,
1665 self.buf.as_ptr() as usize,
1666 ))
1667 }
1668 #[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)"]
1669 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
1670 let mut iter = self.clone();
1671 iter.pos = 0;
1672 for attr in iter {
1673 if let Napi::Threaded(val) = attr? {
1674 return Ok(val);
1675 }
1676 }
1677 Err(ErrorContext::new_missing(
1678 "Napi",
1679 "Threaded",
1680 self.orig_loc,
1681 self.buf.as_ptr() as usize,
1682 ))
1683 }
1684}
1685impl Napi {
1686 pub fn new<'a>(buf: &'a [u8]) -> IterableNapi<'a> {
1687 IterableNapi::with_loc(buf, buf.as_ptr() as usize)
1688 }
1689 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1690 let res = match r#type {
1691 1u16 => "Ifindex",
1692 2u16 => "Id",
1693 3u16 => "Irq",
1694 4u16 => "Pid",
1695 5u16 => "DeferHardIrqs",
1696 6u16 => "GroFlushTimeout",
1697 7u16 => "IrqSuspendTimeout",
1698 8u16 => "Threaded",
1699 _ => return None,
1700 };
1701 Some(res)
1702 }
1703}
1704#[derive(Clone, Copy, Default)]
1705pub struct IterableNapi<'a> {
1706 buf: &'a [u8],
1707 pos: usize,
1708 orig_loc: usize,
1709}
1710impl<'a> IterableNapi<'a> {
1711 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1712 Self {
1713 buf,
1714 pos: 0,
1715 orig_loc,
1716 }
1717 }
1718 pub fn get_buf(&self) -> &'a [u8] {
1719 self.buf
1720 }
1721}
1722impl<'a> Iterator for IterableNapi<'a> {
1723 type Item = Result<Napi, ErrorContext>;
1724 fn next(&mut self) -> Option<Self::Item> {
1725 if self.buf.len() == self.pos {
1726 return None;
1727 }
1728 let pos = self.pos;
1729 let mut r#type = None;
1730 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1731 r#type = Some(header.r#type);
1732 let res = match header.r#type {
1733 1u16 => Napi::Ifindex({
1734 let res = parse_u32(next);
1735 let Some(val) = res else { break };
1736 val
1737 }),
1738 2u16 => Napi::Id({
1739 let res = parse_u32(next);
1740 let Some(val) = res else { break };
1741 val
1742 }),
1743 3u16 => Napi::Irq({
1744 let res = parse_u32(next);
1745 let Some(val) = res else { break };
1746 val
1747 }),
1748 4u16 => Napi::Pid({
1749 let res = parse_u32(next);
1750 let Some(val) = res else { break };
1751 val
1752 }),
1753 5u16 => Napi::DeferHardIrqs({
1754 let res = parse_u32(next);
1755 let Some(val) = res else { break };
1756 val
1757 }),
1758 6u16 => Napi::GroFlushTimeout({
1759 let res = parse_u32(next);
1760 let Some(val) = res else { break };
1761 val
1762 }),
1763 7u16 => Napi::IrqSuspendTimeout({
1764 let res = parse_u32(next);
1765 let Some(val) = res else { break };
1766 val
1767 }),
1768 8u16 => Napi::Threaded({
1769 let res = parse_u32(next);
1770 let Some(val) = res else { break };
1771 val
1772 }),
1773 n => {
1774 if cfg!(any(test, feature = "deny-unknown-attrs")) {
1775 break;
1776 } else {
1777 continue;
1778 }
1779 }
1780 };
1781 return Some(Ok(res));
1782 }
1783 Some(Err(ErrorContext::new(
1784 "Napi",
1785 r#type.and_then(|t| Napi::attr_from_type(t)),
1786 self.orig_loc,
1787 self.buf.as_ptr().wrapping_add(pos) as usize,
1788 )))
1789 }
1790}
1791impl std::fmt::Debug for IterableNapi<'_> {
1792 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1793 let mut fmt = f.debug_struct("Napi");
1794 for attr in self.clone() {
1795 let attr = match attr {
1796 Ok(a) => a,
1797 Err(err) => {
1798 fmt.finish()?;
1799 f.write_str("Err(")?;
1800 err.fmt(f)?;
1801 return f.write_str(")");
1802 }
1803 };
1804 match attr {
1805 Napi::Ifindex(val) => fmt.field("Ifindex", &val),
1806 Napi::Id(val) => fmt.field("Id", &val),
1807 Napi::Irq(val) => fmt.field("Irq", &val),
1808 Napi::Pid(val) => fmt.field("Pid", &val),
1809 Napi::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
1810 Napi::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
1811 Napi::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
1812 Napi::Threaded(val) => fmt.field(
1813 "Threaded",
1814 &FormatEnum(val.into(), NapiThreaded::from_value),
1815 ),
1816 };
1817 }
1818 fmt.finish()
1819 }
1820}
1821impl IterableNapi<'_> {
1822 pub fn lookup_attr(
1823 &self,
1824 offset: usize,
1825 missing_type: Option<u16>,
1826 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1827 let mut stack = Vec::new();
1828 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1829 if cur == offset {
1830 stack.push(("Napi", offset));
1831 return (stack, missing_type.and_then(|t| Napi::attr_from_type(t)));
1832 }
1833 if cur > offset || cur + self.buf.len() < offset {
1834 return (stack, None);
1835 }
1836 let mut attrs = self.clone();
1837 let mut last_off = cur + attrs.pos;
1838 while let Some(attr) = attrs.next() {
1839 let Ok(attr) = attr else { break };
1840 match attr {
1841 Napi::Ifindex(val) => {
1842 if last_off == offset {
1843 stack.push(("Ifindex", last_off));
1844 break;
1845 }
1846 }
1847 Napi::Id(val) => {
1848 if last_off == offset {
1849 stack.push(("Id", last_off));
1850 break;
1851 }
1852 }
1853 Napi::Irq(val) => {
1854 if last_off == offset {
1855 stack.push(("Irq", last_off));
1856 break;
1857 }
1858 }
1859 Napi::Pid(val) => {
1860 if last_off == offset {
1861 stack.push(("Pid", last_off));
1862 break;
1863 }
1864 }
1865 Napi::DeferHardIrqs(val) => {
1866 if last_off == offset {
1867 stack.push(("DeferHardIrqs", last_off));
1868 break;
1869 }
1870 }
1871 Napi::GroFlushTimeout(val) => {
1872 if last_off == offset {
1873 stack.push(("GroFlushTimeout", last_off));
1874 break;
1875 }
1876 }
1877 Napi::IrqSuspendTimeout(val) => {
1878 if last_off == offset {
1879 stack.push(("IrqSuspendTimeout", last_off));
1880 break;
1881 }
1882 }
1883 Napi::Threaded(val) => {
1884 if last_off == offset {
1885 stack.push(("Threaded", last_off));
1886 break;
1887 }
1888 }
1889 _ => {}
1890 };
1891 last_off = cur + attrs.pos;
1892 }
1893 if !stack.is_empty() {
1894 stack.push(("Napi", cur));
1895 }
1896 (stack, None)
1897 }
1898}
1899#[derive(Clone)]
1900pub enum XskInfo {}
1901impl<'a> IterableXskInfo<'a> {}
1902impl XskInfo {
1903 pub fn new<'a>(buf: &'a [u8]) -> IterableXskInfo<'a> {
1904 IterableXskInfo::with_loc(buf, buf.as_ptr() as usize)
1905 }
1906 fn attr_from_type(r#type: u16) -> Option<&'static str> {
1907 None
1908 }
1909}
1910#[derive(Clone, Copy, Default)]
1911pub struct IterableXskInfo<'a> {
1912 buf: &'a [u8],
1913 pos: usize,
1914 orig_loc: usize,
1915}
1916impl<'a> IterableXskInfo<'a> {
1917 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
1918 Self {
1919 buf,
1920 pos: 0,
1921 orig_loc,
1922 }
1923 }
1924 pub fn get_buf(&self) -> &'a [u8] {
1925 self.buf
1926 }
1927}
1928impl<'a> Iterator for IterableXskInfo<'a> {
1929 type Item = Result<XskInfo, ErrorContext>;
1930 fn next(&mut self) -> Option<Self::Item> {
1931 if self.buf.len() == self.pos {
1932 return None;
1933 }
1934 let pos = self.pos;
1935 let mut r#type = None;
1936 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
1937 r#type = Some(header.r#type);
1938 let res = match header.r#type {
1939 n => {
1940 if cfg!(any(test, feature = "deny-unknown-attrs")) {
1941 break;
1942 } else {
1943 continue;
1944 }
1945 }
1946 };
1947 return Some(Ok(res));
1948 }
1949 Some(Err(ErrorContext::new(
1950 "XskInfo",
1951 r#type.and_then(|t| XskInfo::attr_from_type(t)),
1952 self.orig_loc,
1953 self.buf.as_ptr().wrapping_add(pos) as usize,
1954 )))
1955 }
1956}
1957impl std::fmt::Debug for IterableXskInfo<'_> {
1958 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1959 let mut fmt = f.debug_struct("XskInfo");
1960 for attr in self.clone() {
1961 let attr = match attr {
1962 Ok(a) => a,
1963 Err(err) => {
1964 fmt.finish()?;
1965 f.write_str("Err(")?;
1966 err.fmt(f)?;
1967 return f.write_str(")");
1968 }
1969 };
1970 match attr {};
1971 }
1972 fmt.finish()
1973 }
1974}
1975impl IterableXskInfo<'_> {
1976 pub fn lookup_attr(
1977 &self,
1978 offset: usize,
1979 missing_type: Option<u16>,
1980 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1981 let mut stack = Vec::new();
1982 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
1983 if cur == offset {
1984 stack.push(("XskInfo", offset));
1985 return (stack, missing_type.and_then(|t| XskInfo::attr_from_type(t)));
1986 }
1987 (stack, None)
1988 }
1989}
1990#[derive(Clone)]
1991pub enum Queue<'a> {
1992 #[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."]
1993 Id(u32),
1994 #[doc = "ifindex of the netdevice to which the queue belongs."]
1995 Ifindex(u32),
1996 #[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)"]
1997 Type(u32),
1998 #[doc = "ID of the NAPI instance which services this queue."]
1999 NapiId(u32),
2000 #[doc = "ID of the dmabuf attached to this queue, if any."]
2001 Dmabuf(u32),
2002 #[doc = "io_uring memory provider information."]
2003 IoUring(IterableIoUringProviderInfo<'a>),
2004 #[doc = "XSK information for this queue, if any."]
2005 Xsk(IterableXskInfo<'a>),
2006}
2007impl<'a> IterableQueue<'a> {
2008 #[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."]
2009 pub fn get_id(&self) -> Result<u32, ErrorContext> {
2010 let mut iter = self.clone();
2011 iter.pos = 0;
2012 for attr in iter {
2013 if let Queue::Id(val) = attr? {
2014 return Ok(val);
2015 }
2016 }
2017 Err(ErrorContext::new_missing(
2018 "Queue",
2019 "Id",
2020 self.orig_loc,
2021 self.buf.as_ptr() as usize,
2022 ))
2023 }
2024 #[doc = "ifindex of the netdevice to which the queue belongs."]
2025 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2026 let mut iter = self.clone();
2027 iter.pos = 0;
2028 for attr in iter {
2029 if let Queue::Ifindex(val) = attr? {
2030 return Ok(val);
2031 }
2032 }
2033 Err(ErrorContext::new_missing(
2034 "Queue",
2035 "Ifindex",
2036 self.orig_loc,
2037 self.buf.as_ptr() as usize,
2038 ))
2039 }
2040 #[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)"]
2041 pub fn get_type(&self) -> Result<u32, ErrorContext> {
2042 let mut iter = self.clone();
2043 iter.pos = 0;
2044 for attr in iter {
2045 if let Queue::Type(val) = attr? {
2046 return Ok(val);
2047 }
2048 }
2049 Err(ErrorContext::new_missing(
2050 "Queue",
2051 "Type",
2052 self.orig_loc,
2053 self.buf.as_ptr() as usize,
2054 ))
2055 }
2056 #[doc = "ID of the NAPI instance which services this queue."]
2057 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
2058 let mut iter = self.clone();
2059 iter.pos = 0;
2060 for attr in iter {
2061 if let Queue::NapiId(val) = attr? {
2062 return Ok(val);
2063 }
2064 }
2065 Err(ErrorContext::new_missing(
2066 "Queue",
2067 "NapiId",
2068 self.orig_loc,
2069 self.buf.as_ptr() as usize,
2070 ))
2071 }
2072 #[doc = "ID of the dmabuf attached to this queue, if any."]
2073 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
2074 let mut iter = self.clone();
2075 iter.pos = 0;
2076 for attr in iter {
2077 if let Queue::Dmabuf(val) = attr? {
2078 return Ok(val);
2079 }
2080 }
2081 Err(ErrorContext::new_missing(
2082 "Queue",
2083 "Dmabuf",
2084 self.orig_loc,
2085 self.buf.as_ptr() as usize,
2086 ))
2087 }
2088 #[doc = "io_uring memory provider information."]
2089 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
2090 let mut iter = self.clone();
2091 iter.pos = 0;
2092 for attr in iter {
2093 if let Queue::IoUring(val) = attr? {
2094 return Ok(val);
2095 }
2096 }
2097 Err(ErrorContext::new_missing(
2098 "Queue",
2099 "IoUring",
2100 self.orig_loc,
2101 self.buf.as_ptr() as usize,
2102 ))
2103 }
2104 #[doc = "XSK information for this queue, if any."]
2105 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
2106 let mut iter = self.clone();
2107 iter.pos = 0;
2108 for attr in iter {
2109 if let Queue::Xsk(val) = attr? {
2110 return Ok(val);
2111 }
2112 }
2113 Err(ErrorContext::new_missing(
2114 "Queue",
2115 "Xsk",
2116 self.orig_loc,
2117 self.buf.as_ptr() as usize,
2118 ))
2119 }
2120}
2121impl Queue<'_> {
2122 pub fn new<'a>(buf: &'a [u8]) -> IterableQueue<'a> {
2123 IterableQueue::with_loc(buf, buf.as_ptr() as usize)
2124 }
2125 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2126 let res = match r#type {
2127 1u16 => "Id",
2128 2u16 => "Ifindex",
2129 3u16 => "Type",
2130 4u16 => "NapiId",
2131 5u16 => "Dmabuf",
2132 6u16 => "IoUring",
2133 7u16 => "Xsk",
2134 _ => return None,
2135 };
2136 Some(res)
2137 }
2138}
2139#[derive(Clone, Copy, Default)]
2140pub struct IterableQueue<'a> {
2141 buf: &'a [u8],
2142 pos: usize,
2143 orig_loc: usize,
2144}
2145impl<'a> IterableQueue<'a> {
2146 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2147 Self {
2148 buf,
2149 pos: 0,
2150 orig_loc,
2151 }
2152 }
2153 pub fn get_buf(&self) -> &'a [u8] {
2154 self.buf
2155 }
2156}
2157impl<'a> Iterator for IterableQueue<'a> {
2158 type Item = Result<Queue<'a>, ErrorContext>;
2159 fn next(&mut self) -> Option<Self::Item> {
2160 if self.buf.len() == self.pos {
2161 return None;
2162 }
2163 let pos = self.pos;
2164 let mut r#type = None;
2165 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2166 r#type = Some(header.r#type);
2167 let res = match header.r#type {
2168 1u16 => Queue::Id({
2169 let res = parse_u32(next);
2170 let Some(val) = res else { break };
2171 val
2172 }),
2173 2u16 => Queue::Ifindex({
2174 let res = parse_u32(next);
2175 let Some(val) = res else { break };
2176 val
2177 }),
2178 3u16 => Queue::Type({
2179 let res = parse_u32(next);
2180 let Some(val) = res else { break };
2181 val
2182 }),
2183 4u16 => Queue::NapiId({
2184 let res = parse_u32(next);
2185 let Some(val) = res else { break };
2186 val
2187 }),
2188 5u16 => Queue::Dmabuf({
2189 let res = parse_u32(next);
2190 let Some(val) = res else { break };
2191 val
2192 }),
2193 6u16 => Queue::IoUring({
2194 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
2195 let Some(val) = res else { break };
2196 val
2197 }),
2198 7u16 => Queue::Xsk({
2199 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
2200 let Some(val) = res else { break };
2201 val
2202 }),
2203 n => {
2204 if cfg!(any(test, feature = "deny-unknown-attrs")) {
2205 break;
2206 } else {
2207 continue;
2208 }
2209 }
2210 };
2211 return Some(Ok(res));
2212 }
2213 Some(Err(ErrorContext::new(
2214 "Queue",
2215 r#type.and_then(|t| Queue::attr_from_type(t)),
2216 self.orig_loc,
2217 self.buf.as_ptr().wrapping_add(pos) as usize,
2218 )))
2219 }
2220}
2221impl<'a> std::fmt::Debug for IterableQueue<'_> {
2222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2223 let mut fmt = f.debug_struct("Queue");
2224 for attr in self.clone() {
2225 let attr = match attr {
2226 Ok(a) => a,
2227 Err(err) => {
2228 fmt.finish()?;
2229 f.write_str("Err(")?;
2230 err.fmt(f)?;
2231 return f.write_str(")");
2232 }
2233 };
2234 match attr {
2235 Queue::Id(val) => fmt.field("Id", &val),
2236 Queue::Ifindex(val) => fmt.field("Ifindex", &val),
2237 Queue::Type(val) => {
2238 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
2239 }
2240 Queue::NapiId(val) => fmt.field("NapiId", &val),
2241 Queue::Dmabuf(val) => fmt.field("Dmabuf", &val),
2242 Queue::IoUring(val) => fmt.field("IoUring", &val),
2243 Queue::Xsk(val) => fmt.field("Xsk", &val),
2244 };
2245 }
2246 fmt.finish()
2247 }
2248}
2249impl IterableQueue<'_> {
2250 pub fn lookup_attr(
2251 &self,
2252 offset: usize,
2253 missing_type: Option<u16>,
2254 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
2255 let mut stack = Vec::new();
2256 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
2257 if cur == offset {
2258 stack.push(("Queue", offset));
2259 return (stack, missing_type.and_then(|t| Queue::attr_from_type(t)));
2260 }
2261 if cur > offset || cur + self.buf.len() < offset {
2262 return (stack, None);
2263 }
2264 let mut attrs = self.clone();
2265 let mut last_off = cur + attrs.pos;
2266 let mut missing = None;
2267 while let Some(attr) = attrs.next() {
2268 let Ok(attr) = attr else { break };
2269 match attr {
2270 Queue::Id(val) => {
2271 if last_off == offset {
2272 stack.push(("Id", last_off));
2273 break;
2274 }
2275 }
2276 Queue::Ifindex(val) => {
2277 if last_off == offset {
2278 stack.push(("Ifindex", last_off));
2279 break;
2280 }
2281 }
2282 Queue::Type(val) => {
2283 if last_off == offset {
2284 stack.push(("Type", last_off));
2285 break;
2286 }
2287 }
2288 Queue::NapiId(val) => {
2289 if last_off == offset {
2290 stack.push(("NapiId", last_off));
2291 break;
2292 }
2293 }
2294 Queue::Dmabuf(val) => {
2295 if last_off == offset {
2296 stack.push(("Dmabuf", last_off));
2297 break;
2298 }
2299 }
2300 Queue::IoUring(val) => {
2301 (stack, missing) = val.lookup_attr(offset, missing_type);
2302 if !stack.is_empty() {
2303 break;
2304 }
2305 }
2306 Queue::Xsk(val) => {
2307 (stack, missing) = val.lookup_attr(offset, missing_type);
2308 if !stack.is_empty() {
2309 break;
2310 }
2311 }
2312 _ => {}
2313 };
2314 last_off = cur + attrs.pos;
2315 }
2316 if !stack.is_empty() {
2317 stack.push(("Queue", cur));
2318 }
2319 (stack, missing)
2320 }
2321}
2322#[derive(Clone)]
2323pub enum Qstats {
2324 #[doc = "ifindex of the netdevice to which stats belong."]
2325 Ifindex(u32),
2326 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2327 QueueType(u32),
2328 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2329 QueueId(u32),
2330 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2331 Scope(u32),
2332 #[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"]
2333 RxPackets(u32),
2334 #[doc = "Successfully received bytes, see `rx-packets`."]
2335 RxBytes(u32),
2336 #[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"]
2337 TxPackets(u32),
2338 #[doc = "Successfully sent bytes, see `tx-packets`."]
2339 TxBytes(u32),
2340 #[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"]
2341 RxAllocFail(u32),
2342 #[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"]
2343 RxHwDrops(u32),
2344 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2345 RxHwDropOverruns(u32),
2346 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2347 RxCsumComplete(u32),
2348 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2349 RxCsumUnnecessary(u32),
2350 #[doc = "Number of packets that were not checksummed by device."]
2351 RxCsumNone(u32),
2352 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2353 RxCsumBad(u32),
2354 #[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"]
2355 RxHwGroPackets(u32),
2356 #[doc = "See `rx-hw-gro-packets`."]
2357 RxHwGroBytes(u32),
2358 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2359 RxHwGroWirePackets(u32),
2360 #[doc = "See `rx-hw-gro-wire-packets`."]
2361 RxHwGroWireBytes(u32),
2362 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2363 RxHwDropRatelimits(u32),
2364 #[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"]
2365 TxHwDrops(u32),
2366 #[doc = "Number of packets dropped because they were invalid or malformed."]
2367 TxHwDropErrors(u32),
2368 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2369 TxCsumNone(u32),
2370 #[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"]
2371 TxNeedsCsum(u32),
2372 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2373 TxHwGsoPackets(u32),
2374 #[doc = "See `tx-hw-gso-packets`."]
2375 TxHwGsoBytes(u32),
2376 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2377 TxHwGsoWirePackets(u32),
2378 #[doc = "See `tx-hw-gso-wire-packets`."]
2379 TxHwGsoWireBytes(u32),
2380 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2381 TxHwDropRatelimits(u32),
2382 #[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"]
2383 TxStop(u32),
2384 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2385 TxWake(u32),
2386}
2387impl<'a> IterableQstats<'a> {
2388 #[doc = "ifindex of the netdevice to which stats belong."]
2389 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
2390 let mut iter = self.clone();
2391 iter.pos = 0;
2392 for attr in iter {
2393 if let Qstats::Ifindex(val) = attr? {
2394 return Ok(val);
2395 }
2396 }
2397 Err(ErrorContext::new_missing(
2398 "Qstats",
2399 "Ifindex",
2400 self.orig_loc,
2401 self.buf.as_ptr() as usize,
2402 ))
2403 }
2404 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
2405 pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
2406 let mut iter = self.clone();
2407 iter.pos = 0;
2408 for attr in iter {
2409 if let Qstats::QueueType(val) = attr? {
2410 return Ok(val);
2411 }
2412 }
2413 Err(ErrorContext::new_missing(
2414 "Qstats",
2415 "QueueType",
2416 self.orig_loc,
2417 self.buf.as_ptr() as usize,
2418 ))
2419 }
2420 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
2421 pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
2422 let mut iter = self.clone();
2423 iter.pos = 0;
2424 for attr in iter {
2425 if let Qstats::QueueId(val) = attr? {
2426 return Ok(val);
2427 }
2428 }
2429 Err(ErrorContext::new_missing(
2430 "Qstats",
2431 "QueueId",
2432 self.orig_loc,
2433 self.buf.as_ptr() as usize,
2434 ))
2435 }
2436 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
2437 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
2438 let mut iter = self.clone();
2439 iter.pos = 0;
2440 for attr in iter {
2441 if let Qstats::Scope(val) = attr? {
2442 return Ok(val);
2443 }
2444 }
2445 Err(ErrorContext::new_missing(
2446 "Qstats",
2447 "Scope",
2448 self.orig_loc,
2449 self.buf.as_ptr() as usize,
2450 ))
2451 }
2452 #[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"]
2453 pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
2454 let mut iter = self.clone();
2455 iter.pos = 0;
2456 for attr in iter {
2457 if let Qstats::RxPackets(val) = attr? {
2458 return Ok(val);
2459 }
2460 }
2461 Err(ErrorContext::new_missing(
2462 "Qstats",
2463 "RxPackets",
2464 self.orig_loc,
2465 self.buf.as_ptr() as usize,
2466 ))
2467 }
2468 #[doc = "Successfully received bytes, see `rx-packets`."]
2469 pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
2470 let mut iter = self.clone();
2471 iter.pos = 0;
2472 for attr in iter {
2473 if let Qstats::RxBytes(val) = attr? {
2474 return Ok(val);
2475 }
2476 }
2477 Err(ErrorContext::new_missing(
2478 "Qstats",
2479 "RxBytes",
2480 self.orig_loc,
2481 self.buf.as_ptr() as usize,
2482 ))
2483 }
2484 #[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"]
2485 pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
2486 let mut iter = self.clone();
2487 iter.pos = 0;
2488 for attr in iter {
2489 if let Qstats::TxPackets(val) = attr? {
2490 return Ok(val);
2491 }
2492 }
2493 Err(ErrorContext::new_missing(
2494 "Qstats",
2495 "TxPackets",
2496 self.orig_loc,
2497 self.buf.as_ptr() as usize,
2498 ))
2499 }
2500 #[doc = "Successfully sent bytes, see `tx-packets`."]
2501 pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
2502 let mut iter = self.clone();
2503 iter.pos = 0;
2504 for attr in iter {
2505 if let Qstats::TxBytes(val) = attr? {
2506 return Ok(val);
2507 }
2508 }
2509 Err(ErrorContext::new_missing(
2510 "Qstats",
2511 "TxBytes",
2512 self.orig_loc,
2513 self.buf.as_ptr() as usize,
2514 ))
2515 }
2516 #[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"]
2517 pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
2518 let mut iter = self.clone();
2519 iter.pos = 0;
2520 for attr in iter {
2521 if let Qstats::RxAllocFail(val) = attr? {
2522 return Ok(val);
2523 }
2524 }
2525 Err(ErrorContext::new_missing(
2526 "Qstats",
2527 "RxAllocFail",
2528 self.orig_loc,
2529 self.buf.as_ptr() as usize,
2530 ))
2531 }
2532 #[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"]
2533 pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
2534 let mut iter = self.clone();
2535 iter.pos = 0;
2536 for attr in iter {
2537 if let Qstats::RxHwDrops(val) = attr? {
2538 return Ok(val);
2539 }
2540 }
2541 Err(ErrorContext::new_missing(
2542 "Qstats",
2543 "RxHwDrops",
2544 self.orig_loc,
2545 self.buf.as_ptr() as usize,
2546 ))
2547 }
2548 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
2549 pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
2550 let mut iter = self.clone();
2551 iter.pos = 0;
2552 for attr in iter {
2553 if let Qstats::RxHwDropOverruns(val) = attr? {
2554 return Ok(val);
2555 }
2556 }
2557 Err(ErrorContext::new_missing(
2558 "Qstats",
2559 "RxHwDropOverruns",
2560 self.orig_loc,
2561 self.buf.as_ptr() as usize,
2562 ))
2563 }
2564 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
2565 pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
2566 let mut iter = self.clone();
2567 iter.pos = 0;
2568 for attr in iter {
2569 if let Qstats::RxCsumComplete(val) = attr? {
2570 return Ok(val);
2571 }
2572 }
2573 Err(ErrorContext::new_missing(
2574 "Qstats",
2575 "RxCsumComplete",
2576 self.orig_loc,
2577 self.buf.as_ptr() as usize,
2578 ))
2579 }
2580 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
2581 pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
2582 let mut iter = self.clone();
2583 iter.pos = 0;
2584 for attr in iter {
2585 if let Qstats::RxCsumUnnecessary(val) = attr? {
2586 return Ok(val);
2587 }
2588 }
2589 Err(ErrorContext::new_missing(
2590 "Qstats",
2591 "RxCsumUnnecessary",
2592 self.orig_loc,
2593 self.buf.as_ptr() as usize,
2594 ))
2595 }
2596 #[doc = "Number of packets that were not checksummed by device."]
2597 pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
2598 let mut iter = self.clone();
2599 iter.pos = 0;
2600 for attr in iter {
2601 if let Qstats::RxCsumNone(val) = attr? {
2602 return Ok(val);
2603 }
2604 }
2605 Err(ErrorContext::new_missing(
2606 "Qstats",
2607 "RxCsumNone",
2608 self.orig_loc,
2609 self.buf.as_ptr() as usize,
2610 ))
2611 }
2612 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
2613 pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
2614 let mut iter = self.clone();
2615 iter.pos = 0;
2616 for attr in iter {
2617 if let Qstats::RxCsumBad(val) = attr? {
2618 return Ok(val);
2619 }
2620 }
2621 Err(ErrorContext::new_missing(
2622 "Qstats",
2623 "RxCsumBad",
2624 self.orig_loc,
2625 self.buf.as_ptr() as usize,
2626 ))
2627 }
2628 #[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"]
2629 pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
2630 let mut iter = self.clone();
2631 iter.pos = 0;
2632 for attr in iter {
2633 if let Qstats::RxHwGroPackets(val) = attr? {
2634 return Ok(val);
2635 }
2636 }
2637 Err(ErrorContext::new_missing(
2638 "Qstats",
2639 "RxHwGroPackets",
2640 self.orig_loc,
2641 self.buf.as_ptr() as usize,
2642 ))
2643 }
2644 #[doc = "See `rx-hw-gro-packets`."]
2645 pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
2646 let mut iter = self.clone();
2647 iter.pos = 0;
2648 for attr in iter {
2649 if let Qstats::RxHwGroBytes(val) = attr? {
2650 return Ok(val);
2651 }
2652 }
2653 Err(ErrorContext::new_missing(
2654 "Qstats",
2655 "RxHwGroBytes",
2656 self.orig_loc,
2657 self.buf.as_ptr() as usize,
2658 ))
2659 }
2660 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
2661 pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
2662 let mut iter = self.clone();
2663 iter.pos = 0;
2664 for attr in iter {
2665 if let Qstats::RxHwGroWirePackets(val) = attr? {
2666 return Ok(val);
2667 }
2668 }
2669 Err(ErrorContext::new_missing(
2670 "Qstats",
2671 "RxHwGroWirePackets",
2672 self.orig_loc,
2673 self.buf.as_ptr() as usize,
2674 ))
2675 }
2676 #[doc = "See `rx-hw-gro-wire-packets`."]
2677 pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
2678 let mut iter = self.clone();
2679 iter.pos = 0;
2680 for attr in iter {
2681 if let Qstats::RxHwGroWireBytes(val) = attr? {
2682 return Ok(val);
2683 }
2684 }
2685 Err(ErrorContext::new_missing(
2686 "Qstats",
2687 "RxHwGroWireBytes",
2688 self.orig_loc,
2689 self.buf.as_ptr() as usize,
2690 ))
2691 }
2692 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
2693 pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2694 let mut iter = self.clone();
2695 iter.pos = 0;
2696 for attr in iter {
2697 if let Qstats::RxHwDropRatelimits(val) = attr? {
2698 return Ok(val);
2699 }
2700 }
2701 Err(ErrorContext::new_missing(
2702 "Qstats",
2703 "RxHwDropRatelimits",
2704 self.orig_loc,
2705 self.buf.as_ptr() as usize,
2706 ))
2707 }
2708 #[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"]
2709 pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
2710 let mut iter = self.clone();
2711 iter.pos = 0;
2712 for attr in iter {
2713 if let Qstats::TxHwDrops(val) = attr? {
2714 return Ok(val);
2715 }
2716 }
2717 Err(ErrorContext::new_missing(
2718 "Qstats",
2719 "TxHwDrops",
2720 self.orig_loc,
2721 self.buf.as_ptr() as usize,
2722 ))
2723 }
2724 #[doc = "Number of packets dropped because they were invalid or malformed."]
2725 pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
2726 let mut iter = self.clone();
2727 iter.pos = 0;
2728 for attr in iter {
2729 if let Qstats::TxHwDropErrors(val) = attr? {
2730 return Ok(val);
2731 }
2732 }
2733 Err(ErrorContext::new_missing(
2734 "Qstats",
2735 "TxHwDropErrors",
2736 self.orig_loc,
2737 self.buf.as_ptr() as usize,
2738 ))
2739 }
2740 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
2741 pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
2742 let mut iter = self.clone();
2743 iter.pos = 0;
2744 for attr in iter {
2745 if let Qstats::TxCsumNone(val) = attr? {
2746 return Ok(val);
2747 }
2748 }
2749 Err(ErrorContext::new_missing(
2750 "Qstats",
2751 "TxCsumNone",
2752 self.orig_loc,
2753 self.buf.as_ptr() as usize,
2754 ))
2755 }
2756 #[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"]
2757 pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
2758 let mut iter = self.clone();
2759 iter.pos = 0;
2760 for attr in iter {
2761 if let Qstats::TxNeedsCsum(val) = attr? {
2762 return Ok(val);
2763 }
2764 }
2765 Err(ErrorContext::new_missing(
2766 "Qstats",
2767 "TxNeedsCsum",
2768 self.orig_loc,
2769 self.buf.as_ptr() as usize,
2770 ))
2771 }
2772 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
2773 pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
2774 let mut iter = self.clone();
2775 iter.pos = 0;
2776 for attr in iter {
2777 if let Qstats::TxHwGsoPackets(val) = attr? {
2778 return Ok(val);
2779 }
2780 }
2781 Err(ErrorContext::new_missing(
2782 "Qstats",
2783 "TxHwGsoPackets",
2784 self.orig_loc,
2785 self.buf.as_ptr() as usize,
2786 ))
2787 }
2788 #[doc = "See `tx-hw-gso-packets`."]
2789 pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
2790 let mut iter = self.clone();
2791 iter.pos = 0;
2792 for attr in iter {
2793 if let Qstats::TxHwGsoBytes(val) = attr? {
2794 return Ok(val);
2795 }
2796 }
2797 Err(ErrorContext::new_missing(
2798 "Qstats",
2799 "TxHwGsoBytes",
2800 self.orig_loc,
2801 self.buf.as_ptr() as usize,
2802 ))
2803 }
2804 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
2805 pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
2806 let mut iter = self.clone();
2807 iter.pos = 0;
2808 for attr in iter {
2809 if let Qstats::TxHwGsoWirePackets(val) = attr? {
2810 return Ok(val);
2811 }
2812 }
2813 Err(ErrorContext::new_missing(
2814 "Qstats",
2815 "TxHwGsoWirePackets",
2816 self.orig_loc,
2817 self.buf.as_ptr() as usize,
2818 ))
2819 }
2820 #[doc = "See `tx-hw-gso-wire-packets`."]
2821 pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
2822 let mut iter = self.clone();
2823 iter.pos = 0;
2824 for attr in iter {
2825 if let Qstats::TxHwGsoWireBytes(val) = attr? {
2826 return Ok(val);
2827 }
2828 }
2829 Err(ErrorContext::new_missing(
2830 "Qstats",
2831 "TxHwGsoWireBytes",
2832 self.orig_loc,
2833 self.buf.as_ptr() as usize,
2834 ))
2835 }
2836 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
2837 pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
2838 let mut iter = self.clone();
2839 iter.pos = 0;
2840 for attr in iter {
2841 if let Qstats::TxHwDropRatelimits(val) = attr? {
2842 return Ok(val);
2843 }
2844 }
2845 Err(ErrorContext::new_missing(
2846 "Qstats",
2847 "TxHwDropRatelimits",
2848 self.orig_loc,
2849 self.buf.as_ptr() as usize,
2850 ))
2851 }
2852 #[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"]
2853 pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
2854 let mut iter = self.clone();
2855 iter.pos = 0;
2856 for attr in iter {
2857 if let Qstats::TxStop(val) = attr? {
2858 return Ok(val);
2859 }
2860 }
2861 Err(ErrorContext::new_missing(
2862 "Qstats",
2863 "TxStop",
2864 self.orig_loc,
2865 self.buf.as_ptr() as usize,
2866 ))
2867 }
2868 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
2869 pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
2870 let mut iter = self.clone();
2871 iter.pos = 0;
2872 for attr in iter {
2873 if let Qstats::TxWake(val) = attr? {
2874 return Ok(val);
2875 }
2876 }
2877 Err(ErrorContext::new_missing(
2878 "Qstats",
2879 "TxWake",
2880 self.orig_loc,
2881 self.buf.as_ptr() as usize,
2882 ))
2883 }
2884}
2885impl Qstats {
2886 pub fn new<'a>(buf: &'a [u8]) -> IterableQstats<'a> {
2887 IterableQstats::with_loc(buf, buf.as_ptr() as usize)
2888 }
2889 fn attr_from_type(r#type: u16) -> Option<&'static str> {
2890 let res = match r#type {
2891 1u16 => "Ifindex",
2892 2u16 => "QueueType",
2893 3u16 => "QueueId",
2894 4u16 => "Scope",
2895 8u16 => "RxPackets",
2896 9u16 => "RxBytes",
2897 10u16 => "TxPackets",
2898 11u16 => "TxBytes",
2899 12u16 => "RxAllocFail",
2900 13u16 => "RxHwDrops",
2901 14u16 => "RxHwDropOverruns",
2902 15u16 => "RxCsumComplete",
2903 16u16 => "RxCsumUnnecessary",
2904 17u16 => "RxCsumNone",
2905 18u16 => "RxCsumBad",
2906 19u16 => "RxHwGroPackets",
2907 20u16 => "RxHwGroBytes",
2908 21u16 => "RxHwGroWirePackets",
2909 22u16 => "RxHwGroWireBytes",
2910 23u16 => "RxHwDropRatelimits",
2911 24u16 => "TxHwDrops",
2912 25u16 => "TxHwDropErrors",
2913 26u16 => "TxCsumNone",
2914 27u16 => "TxNeedsCsum",
2915 28u16 => "TxHwGsoPackets",
2916 29u16 => "TxHwGsoBytes",
2917 30u16 => "TxHwGsoWirePackets",
2918 31u16 => "TxHwGsoWireBytes",
2919 32u16 => "TxHwDropRatelimits",
2920 33u16 => "TxStop",
2921 34u16 => "TxWake",
2922 _ => return None,
2923 };
2924 Some(res)
2925 }
2926}
2927#[derive(Clone, Copy, Default)]
2928pub struct IterableQstats<'a> {
2929 buf: &'a [u8],
2930 pos: usize,
2931 orig_loc: usize,
2932}
2933impl<'a> IterableQstats<'a> {
2934 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
2935 Self {
2936 buf,
2937 pos: 0,
2938 orig_loc,
2939 }
2940 }
2941 pub fn get_buf(&self) -> &'a [u8] {
2942 self.buf
2943 }
2944}
2945impl<'a> Iterator for IterableQstats<'a> {
2946 type Item = Result<Qstats, ErrorContext>;
2947 fn next(&mut self) -> Option<Self::Item> {
2948 if self.buf.len() == self.pos {
2949 return None;
2950 }
2951 let pos = self.pos;
2952 let mut r#type = None;
2953 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
2954 r#type = Some(header.r#type);
2955 let res = match header.r#type {
2956 1u16 => Qstats::Ifindex({
2957 let res = parse_u32(next);
2958 let Some(val) = res else { break };
2959 val
2960 }),
2961 2u16 => Qstats::QueueType({
2962 let res = parse_u32(next);
2963 let Some(val) = res else { break };
2964 val
2965 }),
2966 3u16 => Qstats::QueueId({
2967 let res = parse_u32(next);
2968 let Some(val) = res else { break };
2969 val
2970 }),
2971 4u16 => Qstats::Scope({
2972 let res = parse_u32(next);
2973 let Some(val) = res else { break };
2974 val
2975 }),
2976 8u16 => Qstats::RxPackets({
2977 let res = parse_u32(next);
2978 let Some(val) = res else { break };
2979 val
2980 }),
2981 9u16 => Qstats::RxBytes({
2982 let res = parse_u32(next);
2983 let Some(val) = res else { break };
2984 val
2985 }),
2986 10u16 => Qstats::TxPackets({
2987 let res = parse_u32(next);
2988 let Some(val) = res else { break };
2989 val
2990 }),
2991 11u16 => Qstats::TxBytes({
2992 let res = parse_u32(next);
2993 let Some(val) = res else { break };
2994 val
2995 }),
2996 12u16 => Qstats::RxAllocFail({
2997 let res = parse_u32(next);
2998 let Some(val) = res else { break };
2999 val
3000 }),
3001 13u16 => Qstats::RxHwDrops({
3002 let res = parse_u32(next);
3003 let Some(val) = res else { break };
3004 val
3005 }),
3006 14u16 => Qstats::RxHwDropOverruns({
3007 let res = parse_u32(next);
3008 let Some(val) = res else { break };
3009 val
3010 }),
3011 15u16 => Qstats::RxCsumComplete({
3012 let res = parse_u32(next);
3013 let Some(val) = res else { break };
3014 val
3015 }),
3016 16u16 => Qstats::RxCsumUnnecessary({
3017 let res = parse_u32(next);
3018 let Some(val) = res else { break };
3019 val
3020 }),
3021 17u16 => Qstats::RxCsumNone({
3022 let res = parse_u32(next);
3023 let Some(val) = res else { break };
3024 val
3025 }),
3026 18u16 => Qstats::RxCsumBad({
3027 let res = parse_u32(next);
3028 let Some(val) = res else { break };
3029 val
3030 }),
3031 19u16 => Qstats::RxHwGroPackets({
3032 let res = parse_u32(next);
3033 let Some(val) = res else { break };
3034 val
3035 }),
3036 20u16 => Qstats::RxHwGroBytes({
3037 let res = parse_u32(next);
3038 let Some(val) = res else { break };
3039 val
3040 }),
3041 21u16 => Qstats::RxHwGroWirePackets({
3042 let res = parse_u32(next);
3043 let Some(val) = res else { break };
3044 val
3045 }),
3046 22u16 => Qstats::RxHwGroWireBytes({
3047 let res = parse_u32(next);
3048 let Some(val) = res else { break };
3049 val
3050 }),
3051 23u16 => Qstats::RxHwDropRatelimits({
3052 let res = parse_u32(next);
3053 let Some(val) = res else { break };
3054 val
3055 }),
3056 24u16 => Qstats::TxHwDrops({
3057 let res = parse_u32(next);
3058 let Some(val) = res else { break };
3059 val
3060 }),
3061 25u16 => Qstats::TxHwDropErrors({
3062 let res = parse_u32(next);
3063 let Some(val) = res else { break };
3064 val
3065 }),
3066 26u16 => Qstats::TxCsumNone({
3067 let res = parse_u32(next);
3068 let Some(val) = res else { break };
3069 val
3070 }),
3071 27u16 => Qstats::TxNeedsCsum({
3072 let res = parse_u32(next);
3073 let Some(val) = res else { break };
3074 val
3075 }),
3076 28u16 => Qstats::TxHwGsoPackets({
3077 let res = parse_u32(next);
3078 let Some(val) = res else { break };
3079 val
3080 }),
3081 29u16 => Qstats::TxHwGsoBytes({
3082 let res = parse_u32(next);
3083 let Some(val) = res else { break };
3084 val
3085 }),
3086 30u16 => Qstats::TxHwGsoWirePackets({
3087 let res = parse_u32(next);
3088 let Some(val) = res else { break };
3089 val
3090 }),
3091 31u16 => Qstats::TxHwGsoWireBytes({
3092 let res = parse_u32(next);
3093 let Some(val) = res else { break };
3094 val
3095 }),
3096 32u16 => Qstats::TxHwDropRatelimits({
3097 let res = parse_u32(next);
3098 let Some(val) = res else { break };
3099 val
3100 }),
3101 33u16 => Qstats::TxStop({
3102 let res = parse_u32(next);
3103 let Some(val) = res else { break };
3104 val
3105 }),
3106 34u16 => Qstats::TxWake({
3107 let res = parse_u32(next);
3108 let Some(val) = res else { break };
3109 val
3110 }),
3111 n => {
3112 if cfg!(any(test, feature = "deny-unknown-attrs")) {
3113 break;
3114 } else {
3115 continue;
3116 }
3117 }
3118 };
3119 return Some(Ok(res));
3120 }
3121 Some(Err(ErrorContext::new(
3122 "Qstats",
3123 r#type.and_then(|t| Qstats::attr_from_type(t)),
3124 self.orig_loc,
3125 self.buf.as_ptr().wrapping_add(pos) as usize,
3126 )))
3127 }
3128}
3129impl std::fmt::Debug for IterableQstats<'_> {
3130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3131 let mut fmt = f.debug_struct("Qstats");
3132 for attr in self.clone() {
3133 let attr = match attr {
3134 Ok(a) => a,
3135 Err(err) => {
3136 fmt.finish()?;
3137 f.write_str("Err(")?;
3138 err.fmt(f)?;
3139 return f.write_str(")");
3140 }
3141 };
3142 match attr {
3143 Qstats::Ifindex(val) => fmt.field("Ifindex", &val),
3144 Qstats::QueueType(val) => {
3145 fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
3146 }
3147 Qstats::QueueId(val) => fmt.field("QueueId", &val),
3148 Qstats::Scope(val) => {
3149 fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
3150 }
3151 Qstats::RxPackets(val) => fmt.field("RxPackets", &val),
3152 Qstats::RxBytes(val) => fmt.field("RxBytes", &val),
3153 Qstats::TxPackets(val) => fmt.field("TxPackets", &val),
3154 Qstats::TxBytes(val) => fmt.field("TxBytes", &val),
3155 Qstats::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
3156 Qstats::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
3157 Qstats::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
3158 Qstats::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
3159 Qstats::RxCsumUnnecessary(val) => fmt.field("RxCsumUnnecessary", &val),
3160 Qstats::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
3161 Qstats::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
3162 Qstats::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
3163 Qstats::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
3164 Qstats::RxHwGroWirePackets(val) => fmt.field("RxHwGroWirePackets", &val),
3165 Qstats::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
3166 Qstats::RxHwDropRatelimits(val) => fmt.field("RxHwDropRatelimits", &val),
3167 Qstats::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
3168 Qstats::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
3169 Qstats::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
3170 Qstats::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
3171 Qstats::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
3172 Qstats::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
3173 Qstats::TxHwGsoWirePackets(val) => fmt.field("TxHwGsoWirePackets", &val),
3174 Qstats::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
3175 Qstats::TxHwDropRatelimits(val) => fmt.field("TxHwDropRatelimits", &val),
3176 Qstats::TxStop(val) => fmt.field("TxStop", &val),
3177 Qstats::TxWake(val) => fmt.field("TxWake", &val),
3178 };
3179 }
3180 fmt.finish()
3181 }
3182}
3183impl IterableQstats<'_> {
3184 pub fn lookup_attr(
3185 &self,
3186 offset: usize,
3187 missing_type: Option<u16>,
3188 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3189 let mut stack = Vec::new();
3190 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3191 if cur == offset {
3192 stack.push(("Qstats", offset));
3193 return (stack, missing_type.and_then(|t| Qstats::attr_from_type(t)));
3194 }
3195 if cur > offset || cur + self.buf.len() < offset {
3196 return (stack, None);
3197 }
3198 let mut attrs = self.clone();
3199 let mut last_off = cur + attrs.pos;
3200 while let Some(attr) = attrs.next() {
3201 let Ok(attr) = attr else { break };
3202 match attr {
3203 Qstats::Ifindex(val) => {
3204 if last_off == offset {
3205 stack.push(("Ifindex", last_off));
3206 break;
3207 }
3208 }
3209 Qstats::QueueType(val) => {
3210 if last_off == offset {
3211 stack.push(("QueueType", last_off));
3212 break;
3213 }
3214 }
3215 Qstats::QueueId(val) => {
3216 if last_off == offset {
3217 stack.push(("QueueId", last_off));
3218 break;
3219 }
3220 }
3221 Qstats::Scope(val) => {
3222 if last_off == offset {
3223 stack.push(("Scope", last_off));
3224 break;
3225 }
3226 }
3227 Qstats::RxPackets(val) => {
3228 if last_off == offset {
3229 stack.push(("RxPackets", last_off));
3230 break;
3231 }
3232 }
3233 Qstats::RxBytes(val) => {
3234 if last_off == offset {
3235 stack.push(("RxBytes", last_off));
3236 break;
3237 }
3238 }
3239 Qstats::TxPackets(val) => {
3240 if last_off == offset {
3241 stack.push(("TxPackets", last_off));
3242 break;
3243 }
3244 }
3245 Qstats::TxBytes(val) => {
3246 if last_off == offset {
3247 stack.push(("TxBytes", last_off));
3248 break;
3249 }
3250 }
3251 Qstats::RxAllocFail(val) => {
3252 if last_off == offset {
3253 stack.push(("RxAllocFail", last_off));
3254 break;
3255 }
3256 }
3257 Qstats::RxHwDrops(val) => {
3258 if last_off == offset {
3259 stack.push(("RxHwDrops", last_off));
3260 break;
3261 }
3262 }
3263 Qstats::RxHwDropOverruns(val) => {
3264 if last_off == offset {
3265 stack.push(("RxHwDropOverruns", last_off));
3266 break;
3267 }
3268 }
3269 Qstats::RxCsumComplete(val) => {
3270 if last_off == offset {
3271 stack.push(("RxCsumComplete", last_off));
3272 break;
3273 }
3274 }
3275 Qstats::RxCsumUnnecessary(val) => {
3276 if last_off == offset {
3277 stack.push(("RxCsumUnnecessary", last_off));
3278 break;
3279 }
3280 }
3281 Qstats::RxCsumNone(val) => {
3282 if last_off == offset {
3283 stack.push(("RxCsumNone", last_off));
3284 break;
3285 }
3286 }
3287 Qstats::RxCsumBad(val) => {
3288 if last_off == offset {
3289 stack.push(("RxCsumBad", last_off));
3290 break;
3291 }
3292 }
3293 Qstats::RxHwGroPackets(val) => {
3294 if last_off == offset {
3295 stack.push(("RxHwGroPackets", last_off));
3296 break;
3297 }
3298 }
3299 Qstats::RxHwGroBytes(val) => {
3300 if last_off == offset {
3301 stack.push(("RxHwGroBytes", last_off));
3302 break;
3303 }
3304 }
3305 Qstats::RxHwGroWirePackets(val) => {
3306 if last_off == offset {
3307 stack.push(("RxHwGroWirePackets", last_off));
3308 break;
3309 }
3310 }
3311 Qstats::RxHwGroWireBytes(val) => {
3312 if last_off == offset {
3313 stack.push(("RxHwGroWireBytes", last_off));
3314 break;
3315 }
3316 }
3317 Qstats::RxHwDropRatelimits(val) => {
3318 if last_off == offset {
3319 stack.push(("RxHwDropRatelimits", last_off));
3320 break;
3321 }
3322 }
3323 Qstats::TxHwDrops(val) => {
3324 if last_off == offset {
3325 stack.push(("TxHwDrops", last_off));
3326 break;
3327 }
3328 }
3329 Qstats::TxHwDropErrors(val) => {
3330 if last_off == offset {
3331 stack.push(("TxHwDropErrors", last_off));
3332 break;
3333 }
3334 }
3335 Qstats::TxCsumNone(val) => {
3336 if last_off == offset {
3337 stack.push(("TxCsumNone", last_off));
3338 break;
3339 }
3340 }
3341 Qstats::TxNeedsCsum(val) => {
3342 if last_off == offset {
3343 stack.push(("TxNeedsCsum", last_off));
3344 break;
3345 }
3346 }
3347 Qstats::TxHwGsoPackets(val) => {
3348 if last_off == offset {
3349 stack.push(("TxHwGsoPackets", last_off));
3350 break;
3351 }
3352 }
3353 Qstats::TxHwGsoBytes(val) => {
3354 if last_off == offset {
3355 stack.push(("TxHwGsoBytes", last_off));
3356 break;
3357 }
3358 }
3359 Qstats::TxHwGsoWirePackets(val) => {
3360 if last_off == offset {
3361 stack.push(("TxHwGsoWirePackets", last_off));
3362 break;
3363 }
3364 }
3365 Qstats::TxHwGsoWireBytes(val) => {
3366 if last_off == offset {
3367 stack.push(("TxHwGsoWireBytes", last_off));
3368 break;
3369 }
3370 }
3371 Qstats::TxHwDropRatelimits(val) => {
3372 if last_off == offset {
3373 stack.push(("TxHwDropRatelimits", last_off));
3374 break;
3375 }
3376 }
3377 Qstats::TxStop(val) => {
3378 if last_off == offset {
3379 stack.push(("TxStop", last_off));
3380 break;
3381 }
3382 }
3383 Qstats::TxWake(val) => {
3384 if last_off == offset {
3385 stack.push(("TxWake", last_off));
3386 break;
3387 }
3388 }
3389 _ => {}
3390 };
3391 last_off = cur + attrs.pos;
3392 }
3393 if !stack.is_empty() {
3394 stack.push(("Qstats", cur));
3395 }
3396 (stack, None)
3397 }
3398}
3399#[derive(Clone)]
3400pub enum QueueId {
3401 #[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."]
3402 Id(u32),
3403 #[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)"]
3404 Type(u32),
3405}
3406impl<'a> IterableQueueId<'a> {
3407 #[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."]
3408 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3409 let mut iter = self.clone();
3410 iter.pos = 0;
3411 for attr in iter {
3412 if let QueueId::Id(val) = attr? {
3413 return Ok(val);
3414 }
3415 }
3416 Err(ErrorContext::new_missing(
3417 "QueueId",
3418 "Id",
3419 self.orig_loc,
3420 self.buf.as_ptr() as usize,
3421 ))
3422 }
3423 #[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)"]
3424 pub fn get_type(&self) -> Result<u32, ErrorContext> {
3425 let mut iter = self.clone();
3426 iter.pos = 0;
3427 for attr in iter {
3428 if let QueueId::Type(val) = attr? {
3429 return Ok(val);
3430 }
3431 }
3432 Err(ErrorContext::new_missing(
3433 "QueueId",
3434 "Type",
3435 self.orig_loc,
3436 self.buf.as_ptr() as usize,
3437 ))
3438 }
3439}
3440impl QueueId {
3441 pub fn new<'a>(buf: &'a [u8]) -> IterableQueueId<'a> {
3442 IterableQueueId::with_loc(buf, buf.as_ptr() as usize)
3443 }
3444 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3445 Queue::attr_from_type(r#type)
3446 }
3447}
3448#[derive(Clone, Copy, Default)]
3449pub struct IterableQueueId<'a> {
3450 buf: &'a [u8],
3451 pos: usize,
3452 orig_loc: usize,
3453}
3454impl<'a> IterableQueueId<'a> {
3455 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3456 Self {
3457 buf,
3458 pos: 0,
3459 orig_loc,
3460 }
3461 }
3462 pub fn get_buf(&self) -> &'a [u8] {
3463 self.buf
3464 }
3465}
3466impl<'a> Iterator for IterableQueueId<'a> {
3467 type Item = Result<QueueId, ErrorContext>;
3468 fn next(&mut self) -> Option<Self::Item> {
3469 if self.buf.len() == self.pos {
3470 return None;
3471 }
3472 let pos = self.pos;
3473 let mut r#type = None;
3474 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3475 r#type = Some(header.r#type);
3476 let res = match header.r#type {
3477 1u16 => QueueId::Id({
3478 let res = parse_u32(next);
3479 let Some(val) = res else { break };
3480 val
3481 }),
3482 3u16 => QueueId::Type({
3483 let res = parse_u32(next);
3484 let Some(val) = res else { break };
3485 val
3486 }),
3487 n => {
3488 if cfg!(any(test, feature = "deny-unknown-attrs")) {
3489 break;
3490 } else {
3491 continue;
3492 }
3493 }
3494 };
3495 return Some(Ok(res));
3496 }
3497 Some(Err(ErrorContext::new(
3498 "QueueId",
3499 r#type.and_then(|t| QueueId::attr_from_type(t)),
3500 self.orig_loc,
3501 self.buf.as_ptr().wrapping_add(pos) as usize,
3502 )))
3503 }
3504}
3505impl std::fmt::Debug for IterableQueueId<'_> {
3506 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3507 let mut fmt = f.debug_struct("QueueId");
3508 for attr in self.clone() {
3509 let attr = match attr {
3510 Ok(a) => a,
3511 Err(err) => {
3512 fmt.finish()?;
3513 f.write_str("Err(")?;
3514 err.fmt(f)?;
3515 return f.write_str(")");
3516 }
3517 };
3518 match attr {
3519 QueueId::Id(val) => fmt.field("Id", &val),
3520 QueueId::Type(val) => {
3521 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
3522 }
3523 };
3524 }
3525 fmt.finish()
3526 }
3527}
3528impl IterableQueueId<'_> {
3529 pub fn lookup_attr(
3530 &self,
3531 offset: usize,
3532 missing_type: Option<u16>,
3533 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3534 let mut stack = Vec::new();
3535 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3536 if cur == offset {
3537 stack.push(("QueueId", offset));
3538 return (stack, missing_type.and_then(|t| QueueId::attr_from_type(t)));
3539 }
3540 if cur > offset || cur + self.buf.len() < offset {
3541 return (stack, None);
3542 }
3543 let mut attrs = self.clone();
3544 let mut last_off = cur + attrs.pos;
3545 while let Some(attr) = attrs.next() {
3546 let Ok(attr) = attr else { break };
3547 match attr {
3548 QueueId::Id(val) => {
3549 if last_off == offset {
3550 stack.push(("Id", last_off));
3551 break;
3552 }
3553 }
3554 QueueId::Type(val) => {
3555 if last_off == offset {
3556 stack.push(("Type", last_off));
3557 break;
3558 }
3559 }
3560 _ => {}
3561 };
3562 last_off = cur + attrs.pos;
3563 }
3564 if !stack.is_empty() {
3565 stack.push(("QueueId", cur));
3566 }
3567 (stack, None)
3568 }
3569}
3570#[derive(Clone)]
3571pub enum Dmabuf<'a> {
3572 #[doc = "netdev ifindex to bind the dmabuf to."]
3573 Ifindex(u32),
3574 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3575 Queues(IterableQueueId<'a>),
3576 #[doc = "dmabuf file descriptor to bind."]
3577 Fd(u32),
3578 #[doc = "id of the dmabuf binding"]
3579 Id(u32),
3580}
3581impl<'a> IterableDmabuf<'a> {
3582 #[doc = "netdev ifindex to bind the dmabuf to."]
3583 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
3584 let mut iter = self.clone();
3585 iter.pos = 0;
3586 for attr in iter {
3587 if let Dmabuf::Ifindex(val) = attr? {
3588 return Ok(val);
3589 }
3590 }
3591 Err(ErrorContext::new_missing(
3592 "Dmabuf",
3593 "Ifindex",
3594 self.orig_loc,
3595 self.buf.as_ptr() as usize,
3596 ))
3597 }
3598 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
3599 pub fn get_queues(&self) -> MultiAttrIterable<Self, Dmabuf<'a>, IterableQueueId<'a>> {
3600 MultiAttrIterable::new(self.clone(), |variant| {
3601 if let Dmabuf::Queues(val) = variant {
3602 Some(val)
3603 } else {
3604 None
3605 }
3606 })
3607 }
3608 #[doc = "dmabuf file descriptor to bind."]
3609 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
3610 let mut iter = self.clone();
3611 iter.pos = 0;
3612 for attr in iter {
3613 if let Dmabuf::Fd(val) = attr? {
3614 return Ok(val);
3615 }
3616 }
3617 Err(ErrorContext::new_missing(
3618 "Dmabuf",
3619 "Fd",
3620 self.orig_loc,
3621 self.buf.as_ptr() as usize,
3622 ))
3623 }
3624 #[doc = "id of the dmabuf binding"]
3625 pub fn get_id(&self) -> Result<u32, ErrorContext> {
3626 let mut iter = self.clone();
3627 iter.pos = 0;
3628 for attr in iter {
3629 if let Dmabuf::Id(val) = attr? {
3630 return Ok(val);
3631 }
3632 }
3633 Err(ErrorContext::new_missing(
3634 "Dmabuf",
3635 "Id",
3636 self.orig_loc,
3637 self.buf.as_ptr() as usize,
3638 ))
3639 }
3640}
3641impl Dmabuf<'_> {
3642 pub fn new<'a>(buf: &'a [u8]) -> IterableDmabuf<'a> {
3643 IterableDmabuf::with_loc(buf, buf.as_ptr() as usize)
3644 }
3645 fn attr_from_type(r#type: u16) -> Option<&'static str> {
3646 let res = match r#type {
3647 1u16 => "Ifindex",
3648 2u16 => "Queues",
3649 3u16 => "Fd",
3650 4u16 => "Id",
3651 _ => return None,
3652 };
3653 Some(res)
3654 }
3655}
3656#[derive(Clone, Copy, Default)]
3657pub struct IterableDmabuf<'a> {
3658 buf: &'a [u8],
3659 pos: usize,
3660 orig_loc: usize,
3661}
3662impl<'a> IterableDmabuf<'a> {
3663 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
3664 Self {
3665 buf,
3666 pos: 0,
3667 orig_loc,
3668 }
3669 }
3670 pub fn get_buf(&self) -> &'a [u8] {
3671 self.buf
3672 }
3673}
3674impl<'a> Iterator for IterableDmabuf<'a> {
3675 type Item = Result<Dmabuf<'a>, ErrorContext>;
3676 fn next(&mut self) -> Option<Self::Item> {
3677 if self.buf.len() == self.pos {
3678 return None;
3679 }
3680 let pos = self.pos;
3681 let mut r#type = None;
3682 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
3683 r#type = Some(header.r#type);
3684 let res = match header.r#type {
3685 1u16 => Dmabuf::Ifindex({
3686 let res = parse_u32(next);
3687 let Some(val) = res else { break };
3688 val
3689 }),
3690 2u16 => Dmabuf::Queues({
3691 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
3692 let Some(val) = res else { break };
3693 val
3694 }),
3695 3u16 => Dmabuf::Fd({
3696 let res = parse_u32(next);
3697 let Some(val) = res else { break };
3698 val
3699 }),
3700 4u16 => Dmabuf::Id({
3701 let res = parse_u32(next);
3702 let Some(val) = res else { break };
3703 val
3704 }),
3705 n => {
3706 if cfg!(any(test, feature = "deny-unknown-attrs")) {
3707 break;
3708 } else {
3709 continue;
3710 }
3711 }
3712 };
3713 return Some(Ok(res));
3714 }
3715 Some(Err(ErrorContext::new(
3716 "Dmabuf",
3717 r#type.and_then(|t| Dmabuf::attr_from_type(t)),
3718 self.orig_loc,
3719 self.buf.as_ptr().wrapping_add(pos) as usize,
3720 )))
3721 }
3722}
3723impl<'a> std::fmt::Debug for IterableDmabuf<'_> {
3724 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3725 let mut fmt = f.debug_struct("Dmabuf");
3726 for attr in self.clone() {
3727 let attr = match attr {
3728 Ok(a) => a,
3729 Err(err) => {
3730 fmt.finish()?;
3731 f.write_str("Err(")?;
3732 err.fmt(f)?;
3733 return f.write_str(")");
3734 }
3735 };
3736 match attr {
3737 Dmabuf::Ifindex(val) => fmt.field("Ifindex", &val),
3738 Dmabuf::Queues(val) => fmt.field("Queues", &val),
3739 Dmabuf::Fd(val) => fmt.field("Fd", &val),
3740 Dmabuf::Id(val) => fmt.field("Id", &val),
3741 };
3742 }
3743 fmt.finish()
3744 }
3745}
3746impl IterableDmabuf<'_> {
3747 pub fn lookup_attr(
3748 &self,
3749 offset: usize,
3750 missing_type: Option<u16>,
3751 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
3752 let mut stack = Vec::new();
3753 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
3754 if cur == offset {
3755 stack.push(("Dmabuf", offset));
3756 return (stack, missing_type.and_then(|t| Dmabuf::attr_from_type(t)));
3757 }
3758 if cur > offset || cur + self.buf.len() < offset {
3759 return (stack, None);
3760 }
3761 let mut attrs = self.clone();
3762 let mut last_off = cur + attrs.pos;
3763 let mut missing = None;
3764 while let Some(attr) = attrs.next() {
3765 let Ok(attr) = attr else { break };
3766 match attr {
3767 Dmabuf::Ifindex(val) => {
3768 if last_off == offset {
3769 stack.push(("Ifindex", last_off));
3770 break;
3771 }
3772 }
3773 Dmabuf::Queues(val) => {
3774 (stack, missing) = val.lookup_attr(offset, missing_type);
3775 if !stack.is_empty() {
3776 break;
3777 }
3778 }
3779 Dmabuf::Fd(val) => {
3780 if last_off == offset {
3781 stack.push(("Fd", last_off));
3782 break;
3783 }
3784 }
3785 Dmabuf::Id(val) => {
3786 if last_off == offset {
3787 stack.push(("Id", last_off));
3788 break;
3789 }
3790 }
3791 _ => {}
3792 };
3793 last_off = cur + attrs.pos;
3794 }
3795 if !stack.is_empty() {
3796 stack.push(("Dmabuf", cur));
3797 }
3798 (stack, missing)
3799 }
3800}
3801pub struct PushDev<Prev: Rec> {
3802 pub(crate) prev: Option<Prev>,
3803 pub(crate) header_offset: Option<usize>,
3804}
3805impl<Prev: Rec> Rec for PushDev<Prev> {
3806 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3807 self.prev.as_mut().unwrap().as_rec_mut()
3808 }
3809}
3810impl<Prev: Rec> PushDev<Prev> {
3811 pub fn new(prev: Prev) -> Self {
3812 Self {
3813 prev: Some(prev),
3814 header_offset: None,
3815 }
3816 }
3817 pub fn end_nested(mut self) -> Prev {
3818 let mut prev = self.prev.take().unwrap();
3819 if let Some(header_offset) = &self.header_offset {
3820 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3821 }
3822 prev
3823 }
3824 #[doc = "netdev ifindex"]
3825 pub fn push_ifindex(mut self, value: u32) -> Self {
3826 push_header(self.as_rec_mut(), 1u16, 4 as u16);
3827 self.as_rec_mut().extend(value.to_ne_bytes());
3828 self
3829 }
3830 pub fn push_pad(mut self, value: &[u8]) -> Self {
3831 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
3832 self.as_rec_mut().extend(value);
3833 self
3834 }
3835 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
3836 pub fn push_xdp_features(mut self, value: u64) -> Self {
3837 push_header(self.as_rec_mut(), 3u16, 8 as u16);
3838 self.as_rec_mut().extend(value.to_ne_bytes());
3839 self
3840 }
3841 #[doc = "max fragment count supported by ZC driver"]
3842 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
3843 push_header(self.as_rec_mut(), 4u16, 4 as u16);
3844 self.as_rec_mut().extend(value.to_ne_bytes());
3845 self
3846 }
3847 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
3848 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
3849 push_header(self.as_rec_mut(), 5u16, 8 as u16);
3850 self.as_rec_mut().extend(value.to_ne_bytes());
3851 self
3852 }
3853 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
3854 pub fn push_xsk_features(mut self, value: u64) -> Self {
3855 push_header(self.as_rec_mut(), 6u16, 8 as u16);
3856 self.as_rec_mut().extend(value.to_ne_bytes());
3857 self
3858 }
3859}
3860impl<Prev: Rec> Drop for PushDev<Prev> {
3861 fn drop(&mut self) {
3862 if let Some(prev) = &mut self.prev {
3863 if let Some(header_offset) = &self.header_offset {
3864 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3865 }
3866 }
3867 }
3868}
3869pub struct PushIoUringProviderInfo<Prev: Rec> {
3870 pub(crate) prev: Option<Prev>,
3871 pub(crate) header_offset: Option<usize>,
3872}
3873impl<Prev: Rec> Rec for PushIoUringProviderInfo<Prev> {
3874 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3875 self.prev.as_mut().unwrap().as_rec_mut()
3876 }
3877}
3878impl<Prev: Rec> PushIoUringProviderInfo<Prev> {
3879 pub fn new(prev: Prev) -> Self {
3880 Self {
3881 prev: Some(prev),
3882 header_offset: None,
3883 }
3884 }
3885 pub fn end_nested(mut self) -> Prev {
3886 let mut prev = self.prev.take().unwrap();
3887 if let Some(header_offset) = &self.header_offset {
3888 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3889 }
3890 prev
3891 }
3892}
3893impl<Prev: Rec> Drop for PushIoUringProviderInfo<Prev> {
3894 fn drop(&mut self) {
3895 if let Some(prev) = &mut self.prev {
3896 if let Some(header_offset) = &self.header_offset {
3897 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3898 }
3899 }
3900 }
3901}
3902pub struct PushPagePool<Prev: Rec> {
3903 pub(crate) prev: Option<Prev>,
3904 pub(crate) header_offset: Option<usize>,
3905}
3906impl<Prev: Rec> Rec for PushPagePool<Prev> {
3907 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3908 self.prev.as_mut().unwrap().as_rec_mut()
3909 }
3910}
3911impl<Prev: Rec> PushPagePool<Prev> {
3912 pub fn new(prev: Prev) -> Self {
3913 Self {
3914 prev: Some(prev),
3915 header_offset: None,
3916 }
3917 }
3918 pub fn end_nested(mut self) -> Prev {
3919 let mut prev = self.prev.take().unwrap();
3920 if let Some(header_offset) = &self.header_offset {
3921 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3922 }
3923 prev
3924 }
3925 #[doc = "Unique ID of a Page Pool instance."]
3926 pub fn push_id(mut self, value: u32) -> Self {
3927 push_header(self.as_rec_mut(), 1u16, 4 as u16);
3928 self.as_rec_mut().extend(value.to_ne_bytes());
3929 self
3930 }
3931 #[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"]
3932 pub fn push_ifindex(mut self, value: u32) -> Self {
3933 push_header(self.as_rec_mut(), 2u16, 4 as u16);
3934 self.as_rec_mut().extend(value.to_ne_bytes());
3935 self
3936 }
3937 #[doc = "Id of NAPI using this Page Pool instance."]
3938 pub fn push_napi_id(mut self, value: u32) -> Self {
3939 push_header(self.as_rec_mut(), 3u16, 4 as u16);
3940 self.as_rec_mut().extend(value.to_ne_bytes());
3941 self
3942 }
3943 #[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"]
3944 pub fn push_inflight(mut self, value: u32) -> Self {
3945 push_header(self.as_rec_mut(), 4u16, 4 as u16);
3946 self.as_rec_mut().extend(value.to_ne_bytes());
3947 self
3948 }
3949 #[doc = "Amount of memory held by inflight pages.\n"]
3950 pub fn push_inflight_mem(mut self, value: u32) -> Self {
3951 push_header(self.as_rec_mut(), 5u16, 4 as u16);
3952 self.as_rec_mut().extend(value.to_ne_bytes());
3953 self
3954 }
3955 #[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"]
3956 pub fn push_detach_time(mut self, value: u32) -> Self {
3957 push_header(self.as_rec_mut(), 6u16, 4 as u16);
3958 self.as_rec_mut().extend(value.to_ne_bytes());
3959 self
3960 }
3961 #[doc = "ID of the dmabuf this page-pool is attached to."]
3962 pub fn push_dmabuf(mut self, value: u32) -> Self {
3963 push_header(self.as_rec_mut(), 7u16, 4 as u16);
3964 self.as_rec_mut().extend(value.to_ne_bytes());
3965 self
3966 }
3967 #[doc = "io-uring memory provider information."]
3968 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
3969 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
3970 PushIoUringProviderInfo {
3971 prev: Some(self),
3972 header_offset: Some(header_offset),
3973 }
3974 }
3975}
3976impl<Prev: Rec> Drop for PushPagePool<Prev> {
3977 fn drop(&mut self) {
3978 if let Some(prev) = &mut self.prev {
3979 if let Some(header_offset) = &self.header_offset {
3980 finalize_nested_header(prev.as_rec_mut(), *header_offset);
3981 }
3982 }
3983 }
3984}
3985pub struct PushPagePoolInfo<Prev: Rec> {
3986 pub(crate) prev: Option<Prev>,
3987 pub(crate) header_offset: Option<usize>,
3988}
3989impl<Prev: Rec> Rec for PushPagePoolInfo<Prev> {
3990 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
3991 self.prev.as_mut().unwrap().as_rec_mut()
3992 }
3993}
3994impl<Prev: Rec> PushPagePoolInfo<Prev> {
3995 pub fn new(prev: Prev) -> Self {
3996 Self {
3997 prev: Some(prev),
3998 header_offset: None,
3999 }
4000 }
4001 pub fn end_nested(mut self) -> Prev {
4002 let mut prev = self.prev.take().unwrap();
4003 if let Some(header_offset) = &self.header_offset {
4004 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4005 }
4006 prev
4007 }
4008 #[doc = "Unique ID of a Page Pool instance."]
4009 pub fn push_id(mut self, value: u32) -> Self {
4010 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4011 self.as_rec_mut().extend(value.to_ne_bytes());
4012 self
4013 }
4014 #[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"]
4015 pub fn push_ifindex(mut self, value: u32) -> Self {
4016 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4017 self.as_rec_mut().extend(value.to_ne_bytes());
4018 self
4019 }
4020}
4021impl<Prev: Rec> Drop for PushPagePoolInfo<Prev> {
4022 fn drop(&mut self) {
4023 if let Some(prev) = &mut self.prev {
4024 if let Some(header_offset) = &self.header_offset {
4025 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4026 }
4027 }
4028 }
4029}
4030pub struct PushPagePoolStats<Prev: Rec> {
4031 pub(crate) prev: Option<Prev>,
4032 pub(crate) header_offset: Option<usize>,
4033}
4034impl<Prev: Rec> Rec for PushPagePoolStats<Prev> {
4035 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4036 self.prev.as_mut().unwrap().as_rec_mut()
4037 }
4038}
4039impl<Prev: Rec> PushPagePoolStats<Prev> {
4040 pub fn new(prev: Prev) -> Self {
4041 Self {
4042 prev: Some(prev),
4043 header_offset: None,
4044 }
4045 }
4046 pub fn end_nested(mut self) -> Prev {
4047 let mut prev = self.prev.take().unwrap();
4048 if let Some(header_offset) = &self.header_offset {
4049 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4050 }
4051 prev
4052 }
4053 #[doc = "Page pool identifying information."]
4054 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
4055 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
4056 PushPagePoolInfo {
4057 prev: Some(self),
4058 header_offset: Some(header_offset),
4059 }
4060 }
4061 pub fn push_alloc_fast(mut self, value: u32) -> Self {
4062 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4063 self.as_rec_mut().extend(value.to_ne_bytes());
4064 self
4065 }
4066 pub fn push_alloc_slow(mut self, value: u32) -> Self {
4067 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4068 self.as_rec_mut().extend(value.to_ne_bytes());
4069 self
4070 }
4071 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
4072 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4073 self.as_rec_mut().extend(value.to_ne_bytes());
4074 self
4075 }
4076 pub fn push_alloc_empty(mut self, value: u32) -> Self {
4077 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4078 self.as_rec_mut().extend(value.to_ne_bytes());
4079 self
4080 }
4081 pub fn push_alloc_refill(mut self, value: u32) -> Self {
4082 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4083 self.as_rec_mut().extend(value.to_ne_bytes());
4084 self
4085 }
4086 pub fn push_alloc_waive(mut self, value: u32) -> Self {
4087 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4088 self.as_rec_mut().extend(value.to_ne_bytes());
4089 self
4090 }
4091 pub fn push_recycle_cached(mut self, value: u32) -> Self {
4092 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4093 self.as_rec_mut().extend(value.to_ne_bytes());
4094 self
4095 }
4096 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
4097 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4098 self.as_rec_mut().extend(value.to_ne_bytes());
4099 self
4100 }
4101 pub fn push_recycle_ring(mut self, value: u32) -> Self {
4102 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4103 self.as_rec_mut().extend(value.to_ne_bytes());
4104 self
4105 }
4106 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
4107 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4108 self.as_rec_mut().extend(value.to_ne_bytes());
4109 self
4110 }
4111 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
4112 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4113 self.as_rec_mut().extend(value.to_ne_bytes());
4114 self
4115 }
4116}
4117impl<Prev: Rec> Drop for PushPagePoolStats<Prev> {
4118 fn drop(&mut self) {
4119 if let Some(prev) = &mut self.prev {
4120 if let Some(header_offset) = &self.header_offset {
4121 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4122 }
4123 }
4124 }
4125}
4126pub struct PushNapi<Prev: Rec> {
4127 pub(crate) prev: Option<Prev>,
4128 pub(crate) header_offset: Option<usize>,
4129}
4130impl<Prev: Rec> Rec for PushNapi<Prev> {
4131 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4132 self.prev.as_mut().unwrap().as_rec_mut()
4133 }
4134}
4135impl<Prev: Rec> PushNapi<Prev> {
4136 pub fn new(prev: Prev) -> Self {
4137 Self {
4138 prev: Some(prev),
4139 header_offset: None,
4140 }
4141 }
4142 pub fn end_nested(mut self) -> Prev {
4143 let mut prev = self.prev.take().unwrap();
4144 if let Some(header_offset) = &self.header_offset {
4145 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4146 }
4147 prev
4148 }
4149 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
4150 pub fn push_ifindex(mut self, value: u32) -> Self {
4151 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4152 self.as_rec_mut().extend(value.to_ne_bytes());
4153 self
4154 }
4155 #[doc = "ID of the NAPI instance."]
4156 pub fn push_id(mut self, value: u32) -> Self {
4157 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4158 self.as_rec_mut().extend(value.to_ne_bytes());
4159 self
4160 }
4161 #[doc = "The associated interrupt vector number for the napi"]
4162 pub fn push_irq(mut self, value: u32) -> Self {
4163 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4164 self.as_rec_mut().extend(value.to_ne_bytes());
4165 self
4166 }
4167 #[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."]
4168 pub fn push_pid(mut self, value: u32) -> Self {
4169 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4170 self.as_rec_mut().extend(value.to_ne_bytes());
4171 self
4172 }
4173 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
4174 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
4175 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4176 self.as_rec_mut().extend(value.to_ne_bytes());
4177 self
4178 }
4179 #[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."]
4180 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
4181 push_header(self.as_rec_mut(), 6u16, 4 as u16);
4182 self.as_rec_mut().extend(value.to_ne_bytes());
4183 self
4184 }
4185 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
4186 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
4187 push_header(self.as_rec_mut(), 7u16, 4 as u16);
4188 self.as_rec_mut().extend(value.to_ne_bytes());
4189 self
4190 }
4191 #[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)"]
4192 pub fn push_threaded(mut self, value: u32) -> Self {
4193 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4194 self.as_rec_mut().extend(value.to_ne_bytes());
4195 self
4196 }
4197}
4198impl<Prev: Rec> Drop for PushNapi<Prev> {
4199 fn drop(&mut self) {
4200 if let Some(prev) = &mut self.prev {
4201 if let Some(header_offset) = &self.header_offset {
4202 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4203 }
4204 }
4205 }
4206}
4207pub struct PushXskInfo<Prev: Rec> {
4208 pub(crate) prev: Option<Prev>,
4209 pub(crate) header_offset: Option<usize>,
4210}
4211impl<Prev: Rec> Rec for PushXskInfo<Prev> {
4212 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4213 self.prev.as_mut().unwrap().as_rec_mut()
4214 }
4215}
4216impl<Prev: Rec> PushXskInfo<Prev> {
4217 pub fn new(prev: Prev) -> Self {
4218 Self {
4219 prev: Some(prev),
4220 header_offset: None,
4221 }
4222 }
4223 pub fn end_nested(mut self) -> Prev {
4224 let mut prev = self.prev.take().unwrap();
4225 if let Some(header_offset) = &self.header_offset {
4226 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4227 }
4228 prev
4229 }
4230}
4231impl<Prev: Rec> Drop for PushXskInfo<Prev> {
4232 fn drop(&mut self) {
4233 if let Some(prev) = &mut self.prev {
4234 if let Some(header_offset) = &self.header_offset {
4235 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4236 }
4237 }
4238 }
4239}
4240pub struct PushQueue<Prev: Rec> {
4241 pub(crate) prev: Option<Prev>,
4242 pub(crate) header_offset: Option<usize>,
4243}
4244impl<Prev: Rec> Rec for PushQueue<Prev> {
4245 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4246 self.prev.as_mut().unwrap().as_rec_mut()
4247 }
4248}
4249impl<Prev: Rec> PushQueue<Prev> {
4250 pub fn new(prev: Prev) -> Self {
4251 Self {
4252 prev: Some(prev),
4253 header_offset: None,
4254 }
4255 }
4256 pub fn end_nested(mut self) -> Prev {
4257 let mut prev = self.prev.take().unwrap();
4258 if let Some(header_offset) = &self.header_offset {
4259 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4260 }
4261 prev
4262 }
4263 #[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."]
4264 pub fn push_id(mut self, value: u32) -> Self {
4265 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4266 self.as_rec_mut().extend(value.to_ne_bytes());
4267 self
4268 }
4269 #[doc = "ifindex of the netdevice to which the queue belongs."]
4270 pub fn push_ifindex(mut self, value: u32) -> Self {
4271 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4272 self.as_rec_mut().extend(value.to_ne_bytes());
4273 self
4274 }
4275 #[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)"]
4276 pub fn push_type(mut self, value: u32) -> Self {
4277 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4278 self.as_rec_mut().extend(value.to_ne_bytes());
4279 self
4280 }
4281 #[doc = "ID of the NAPI instance which services this queue."]
4282 pub fn push_napi_id(mut self, value: u32) -> Self {
4283 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4284 self.as_rec_mut().extend(value.to_ne_bytes());
4285 self
4286 }
4287 #[doc = "ID of the dmabuf attached to this queue, if any."]
4288 pub fn push_dmabuf(mut self, value: u32) -> Self {
4289 push_header(self.as_rec_mut(), 5u16, 4 as u16);
4290 self.as_rec_mut().extend(value.to_ne_bytes());
4291 self
4292 }
4293 #[doc = "io_uring memory provider information."]
4294 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
4295 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
4296 PushIoUringProviderInfo {
4297 prev: Some(self),
4298 header_offset: Some(header_offset),
4299 }
4300 }
4301 #[doc = "XSK information for this queue, if any."]
4302 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
4303 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
4304 PushXskInfo {
4305 prev: Some(self),
4306 header_offset: Some(header_offset),
4307 }
4308 }
4309}
4310impl<Prev: Rec> Drop for PushQueue<Prev> {
4311 fn drop(&mut self) {
4312 if let Some(prev) = &mut self.prev {
4313 if let Some(header_offset) = &self.header_offset {
4314 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4315 }
4316 }
4317 }
4318}
4319pub struct PushQstats<Prev: Rec> {
4320 pub(crate) prev: Option<Prev>,
4321 pub(crate) header_offset: Option<usize>,
4322}
4323impl<Prev: Rec> Rec for PushQstats<Prev> {
4324 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4325 self.prev.as_mut().unwrap().as_rec_mut()
4326 }
4327}
4328impl<Prev: Rec> PushQstats<Prev> {
4329 pub fn new(prev: Prev) -> Self {
4330 Self {
4331 prev: Some(prev),
4332 header_offset: None,
4333 }
4334 }
4335 pub fn end_nested(mut self) -> Prev {
4336 let mut prev = self.prev.take().unwrap();
4337 if let Some(header_offset) = &self.header_offset {
4338 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4339 }
4340 prev
4341 }
4342 #[doc = "ifindex of the netdevice to which stats belong."]
4343 pub fn push_ifindex(mut self, value: u32) -> Self {
4344 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4345 self.as_rec_mut().extend(value.to_ne_bytes());
4346 self
4347 }
4348 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
4349 pub fn push_queue_type(mut self, value: u32) -> Self {
4350 push_header(self.as_rec_mut(), 2u16, 4 as u16);
4351 self.as_rec_mut().extend(value.to_ne_bytes());
4352 self
4353 }
4354 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
4355 pub fn push_queue_id(mut self, value: u32) -> Self {
4356 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4357 self.as_rec_mut().extend(value.to_ne_bytes());
4358 self
4359 }
4360 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
4361 pub fn push_scope(mut self, value: u32) -> Self {
4362 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4363 self.as_rec_mut().extend(value.to_ne_bytes());
4364 self
4365 }
4366 #[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"]
4367 pub fn push_rx_packets(mut self, value: u32) -> Self {
4368 push_header(self.as_rec_mut(), 8u16, 4 as u16);
4369 self.as_rec_mut().extend(value.to_ne_bytes());
4370 self
4371 }
4372 #[doc = "Successfully received bytes, see `rx-packets`."]
4373 pub fn push_rx_bytes(mut self, value: u32) -> Self {
4374 push_header(self.as_rec_mut(), 9u16, 4 as u16);
4375 self.as_rec_mut().extend(value.to_ne_bytes());
4376 self
4377 }
4378 #[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"]
4379 pub fn push_tx_packets(mut self, value: u32) -> Self {
4380 push_header(self.as_rec_mut(), 10u16, 4 as u16);
4381 self.as_rec_mut().extend(value.to_ne_bytes());
4382 self
4383 }
4384 #[doc = "Successfully sent bytes, see `tx-packets`."]
4385 pub fn push_tx_bytes(mut self, value: u32) -> Self {
4386 push_header(self.as_rec_mut(), 11u16, 4 as u16);
4387 self.as_rec_mut().extend(value.to_ne_bytes());
4388 self
4389 }
4390 #[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"]
4391 pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
4392 push_header(self.as_rec_mut(), 12u16, 4 as u16);
4393 self.as_rec_mut().extend(value.to_ne_bytes());
4394 self
4395 }
4396 #[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"]
4397 pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
4398 push_header(self.as_rec_mut(), 13u16, 4 as u16);
4399 self.as_rec_mut().extend(value.to_ne_bytes());
4400 self
4401 }
4402 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
4403 pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
4404 push_header(self.as_rec_mut(), 14u16, 4 as u16);
4405 self.as_rec_mut().extend(value.to_ne_bytes());
4406 self
4407 }
4408 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
4409 pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
4410 push_header(self.as_rec_mut(), 15u16, 4 as u16);
4411 self.as_rec_mut().extend(value.to_ne_bytes());
4412 self
4413 }
4414 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
4415 pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
4416 push_header(self.as_rec_mut(), 16u16, 4 as u16);
4417 self.as_rec_mut().extend(value.to_ne_bytes());
4418 self
4419 }
4420 #[doc = "Number of packets that were not checksummed by device."]
4421 pub fn push_rx_csum_none(mut self, value: u32) -> Self {
4422 push_header(self.as_rec_mut(), 17u16, 4 as u16);
4423 self.as_rec_mut().extend(value.to_ne_bytes());
4424 self
4425 }
4426 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
4427 pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
4428 push_header(self.as_rec_mut(), 18u16, 4 as u16);
4429 self.as_rec_mut().extend(value.to_ne_bytes());
4430 self
4431 }
4432 #[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"]
4433 pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
4434 push_header(self.as_rec_mut(), 19u16, 4 as u16);
4435 self.as_rec_mut().extend(value.to_ne_bytes());
4436 self
4437 }
4438 #[doc = "See `rx-hw-gro-packets`."]
4439 pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
4440 push_header(self.as_rec_mut(), 20u16, 4 as u16);
4441 self.as_rec_mut().extend(value.to_ne_bytes());
4442 self
4443 }
4444 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
4445 pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
4446 push_header(self.as_rec_mut(), 21u16, 4 as u16);
4447 self.as_rec_mut().extend(value.to_ne_bytes());
4448 self
4449 }
4450 #[doc = "See `rx-hw-gro-wire-packets`."]
4451 pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
4452 push_header(self.as_rec_mut(), 22u16, 4 as u16);
4453 self.as_rec_mut().extend(value.to_ne_bytes());
4454 self
4455 }
4456 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
4457 pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4458 push_header(self.as_rec_mut(), 23u16, 4 as u16);
4459 self.as_rec_mut().extend(value.to_ne_bytes());
4460 self
4461 }
4462 #[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"]
4463 pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
4464 push_header(self.as_rec_mut(), 24u16, 4 as u16);
4465 self.as_rec_mut().extend(value.to_ne_bytes());
4466 self
4467 }
4468 #[doc = "Number of packets dropped because they were invalid or malformed."]
4469 pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
4470 push_header(self.as_rec_mut(), 25u16, 4 as u16);
4471 self.as_rec_mut().extend(value.to_ne_bytes());
4472 self
4473 }
4474 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
4475 pub fn push_tx_csum_none(mut self, value: u32) -> Self {
4476 push_header(self.as_rec_mut(), 26u16, 4 as u16);
4477 self.as_rec_mut().extend(value.to_ne_bytes());
4478 self
4479 }
4480 #[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"]
4481 pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
4482 push_header(self.as_rec_mut(), 27u16, 4 as u16);
4483 self.as_rec_mut().extend(value.to_ne_bytes());
4484 self
4485 }
4486 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
4487 pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
4488 push_header(self.as_rec_mut(), 28u16, 4 as u16);
4489 self.as_rec_mut().extend(value.to_ne_bytes());
4490 self
4491 }
4492 #[doc = "See `tx-hw-gso-packets`."]
4493 pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
4494 push_header(self.as_rec_mut(), 29u16, 4 as u16);
4495 self.as_rec_mut().extend(value.to_ne_bytes());
4496 self
4497 }
4498 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
4499 pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
4500 push_header(self.as_rec_mut(), 30u16, 4 as u16);
4501 self.as_rec_mut().extend(value.to_ne_bytes());
4502 self
4503 }
4504 #[doc = "See `tx-hw-gso-wire-packets`."]
4505 pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
4506 push_header(self.as_rec_mut(), 31u16, 4 as u16);
4507 self.as_rec_mut().extend(value.to_ne_bytes());
4508 self
4509 }
4510 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
4511 pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
4512 push_header(self.as_rec_mut(), 32u16, 4 as u16);
4513 self.as_rec_mut().extend(value.to_ne_bytes());
4514 self
4515 }
4516 #[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"]
4517 pub fn push_tx_stop(mut self, value: u32) -> Self {
4518 push_header(self.as_rec_mut(), 33u16, 4 as u16);
4519 self.as_rec_mut().extend(value.to_ne_bytes());
4520 self
4521 }
4522 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
4523 pub fn push_tx_wake(mut self, value: u32) -> Self {
4524 push_header(self.as_rec_mut(), 34u16, 4 as u16);
4525 self.as_rec_mut().extend(value.to_ne_bytes());
4526 self
4527 }
4528}
4529impl<Prev: Rec> Drop for PushQstats<Prev> {
4530 fn drop(&mut self) {
4531 if let Some(prev) = &mut self.prev {
4532 if let Some(header_offset) = &self.header_offset {
4533 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4534 }
4535 }
4536 }
4537}
4538pub struct PushQueueId<Prev: Rec> {
4539 pub(crate) prev: Option<Prev>,
4540 pub(crate) header_offset: Option<usize>,
4541}
4542impl<Prev: Rec> Rec for PushQueueId<Prev> {
4543 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4544 self.prev.as_mut().unwrap().as_rec_mut()
4545 }
4546}
4547impl<Prev: Rec> PushQueueId<Prev> {
4548 pub fn new(prev: Prev) -> Self {
4549 Self {
4550 prev: Some(prev),
4551 header_offset: None,
4552 }
4553 }
4554 pub fn end_nested(mut self) -> Prev {
4555 let mut prev = self.prev.take().unwrap();
4556 if let Some(header_offset) = &self.header_offset {
4557 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4558 }
4559 prev
4560 }
4561 #[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."]
4562 pub fn push_id(mut self, value: u32) -> Self {
4563 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4564 self.as_rec_mut().extend(value.to_ne_bytes());
4565 self
4566 }
4567 #[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)"]
4568 pub fn push_type(mut self, value: u32) -> Self {
4569 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4570 self.as_rec_mut().extend(value.to_ne_bytes());
4571 self
4572 }
4573}
4574impl<Prev: Rec> Drop for PushQueueId<Prev> {
4575 fn drop(&mut self) {
4576 if let Some(prev) = &mut self.prev {
4577 if let Some(header_offset) = &self.header_offset {
4578 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4579 }
4580 }
4581 }
4582}
4583pub struct PushDmabuf<Prev: Rec> {
4584 pub(crate) prev: Option<Prev>,
4585 pub(crate) header_offset: Option<usize>,
4586}
4587impl<Prev: Rec> Rec for PushDmabuf<Prev> {
4588 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4589 self.prev.as_mut().unwrap().as_rec_mut()
4590 }
4591}
4592impl<Prev: Rec> PushDmabuf<Prev> {
4593 pub fn new(prev: Prev) -> Self {
4594 Self {
4595 prev: Some(prev),
4596 header_offset: None,
4597 }
4598 }
4599 pub fn end_nested(mut self) -> Prev {
4600 let mut prev = self.prev.take().unwrap();
4601 if let Some(header_offset) = &self.header_offset {
4602 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4603 }
4604 prev
4605 }
4606 #[doc = "netdev ifindex to bind the dmabuf to."]
4607 pub fn push_ifindex(mut self, value: u32) -> Self {
4608 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4609 self.as_rec_mut().extend(value.to_ne_bytes());
4610 self
4611 }
4612 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
4613 pub fn nested_queues(mut self) -> PushQueueId<Self> {
4614 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
4615 PushQueueId {
4616 prev: Some(self),
4617 header_offset: Some(header_offset),
4618 }
4619 }
4620 #[doc = "dmabuf file descriptor to bind."]
4621 pub fn push_fd(mut self, value: u32) -> Self {
4622 push_header(self.as_rec_mut(), 3u16, 4 as u16);
4623 self.as_rec_mut().extend(value.to_ne_bytes());
4624 self
4625 }
4626 #[doc = "id of the dmabuf binding"]
4627 pub fn push_id(mut self, value: u32) -> Self {
4628 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4629 self.as_rec_mut().extend(value.to_ne_bytes());
4630 self
4631 }
4632}
4633impl<Prev: Rec> Drop for PushDmabuf<Prev> {
4634 fn drop(&mut self) {
4635 if let Some(prev) = &mut self.prev {
4636 if let Some(header_offset) = &self.header_offset {
4637 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4638 }
4639 }
4640 }
4641}
4642#[doc = "Get / dump information about a netdev."]
4643pub struct PushOpDevGetDumpRequest<Prev: Rec> {
4644 pub(crate) prev: Option<Prev>,
4645 pub(crate) header_offset: Option<usize>,
4646}
4647impl<Prev: Rec> Rec for PushOpDevGetDumpRequest<Prev> {
4648 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4649 self.prev.as_mut().unwrap().as_rec_mut()
4650 }
4651}
4652impl<Prev: Rec> PushOpDevGetDumpRequest<Prev> {
4653 pub fn new(mut prev: Prev) -> Self {
4654 Self::write_header(&mut prev);
4655 Self::new_without_header(prev)
4656 }
4657 fn new_without_header(prev: Prev) -> Self {
4658 Self {
4659 prev: Some(prev),
4660 header_offset: None,
4661 }
4662 }
4663 fn write_header(prev: &mut Prev) {
4664 let mut header = PushBuiltinNfgenmsg::new();
4665 header.set_cmd(1u8);
4666 header.set_version(1u8);
4667 prev.as_rec_mut().extend(header.as_slice());
4668 }
4669 pub fn end_nested(mut self) -> Prev {
4670 let mut prev = self.prev.take().unwrap();
4671 if let Some(header_offset) = &self.header_offset {
4672 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4673 }
4674 prev
4675 }
4676}
4677impl<Prev: Rec> Drop for PushOpDevGetDumpRequest<Prev> {
4678 fn drop(&mut self) {
4679 if let Some(prev) = &mut self.prev {
4680 if let Some(header_offset) = &self.header_offset {
4681 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4682 }
4683 }
4684 }
4685}
4686#[doc = "Get / dump information about a netdev."]
4687#[derive(Clone)]
4688pub enum OpDevGetDumpRequest {}
4689impl<'a> IterableOpDevGetDumpRequest<'a> {}
4690impl OpDevGetDumpRequest {
4691 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpRequest<'a> {
4692 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4693 IterableOpDevGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
4694 }
4695 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4696 Dev::attr_from_type(r#type)
4697 }
4698}
4699#[derive(Clone, Copy, Default)]
4700pub struct IterableOpDevGetDumpRequest<'a> {
4701 buf: &'a [u8],
4702 pos: usize,
4703 orig_loc: usize,
4704}
4705impl<'a> IterableOpDevGetDumpRequest<'a> {
4706 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4707 Self {
4708 buf,
4709 pos: 0,
4710 orig_loc,
4711 }
4712 }
4713 pub fn get_buf(&self) -> &'a [u8] {
4714 self.buf
4715 }
4716}
4717impl<'a> Iterator for IterableOpDevGetDumpRequest<'a> {
4718 type Item = Result<OpDevGetDumpRequest, ErrorContext>;
4719 fn next(&mut self) -> Option<Self::Item> {
4720 if self.buf.len() == self.pos {
4721 return None;
4722 }
4723 let pos = self.pos;
4724 let mut r#type = None;
4725 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
4726 r#type = Some(header.r#type);
4727 let res = match header.r#type {
4728 n => {
4729 if cfg!(any(test, feature = "deny-unknown-attrs")) {
4730 break;
4731 } else {
4732 continue;
4733 }
4734 }
4735 };
4736 return Some(Ok(res));
4737 }
4738 Some(Err(ErrorContext::new(
4739 "OpDevGetDumpRequest",
4740 r#type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4741 self.orig_loc,
4742 self.buf.as_ptr().wrapping_add(pos) as usize,
4743 )))
4744 }
4745}
4746impl std::fmt::Debug for IterableOpDevGetDumpRequest<'_> {
4747 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4748 let mut fmt = f.debug_struct("OpDevGetDumpRequest");
4749 for attr in self.clone() {
4750 let attr = match attr {
4751 Ok(a) => a,
4752 Err(err) => {
4753 fmt.finish()?;
4754 f.write_str("Err(")?;
4755 err.fmt(f)?;
4756 return f.write_str(")");
4757 }
4758 };
4759 match attr {};
4760 }
4761 fmt.finish()
4762 }
4763}
4764impl IterableOpDevGetDumpRequest<'_> {
4765 pub fn lookup_attr(
4766 &self,
4767 offset: usize,
4768 missing_type: Option<u16>,
4769 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
4770 let mut stack = Vec::new();
4771 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
4772 if cur == offset + PushBuiltinNfgenmsg::len() {
4773 stack.push(("OpDevGetDumpRequest", offset));
4774 return (
4775 stack,
4776 missing_type.and_then(|t| OpDevGetDumpRequest::attr_from_type(t)),
4777 );
4778 }
4779 (stack, None)
4780 }
4781}
4782#[doc = "Get / dump information about a netdev."]
4783pub struct PushOpDevGetDumpReply<Prev: Rec> {
4784 pub(crate) prev: Option<Prev>,
4785 pub(crate) header_offset: Option<usize>,
4786}
4787impl<Prev: Rec> Rec for PushOpDevGetDumpReply<Prev> {
4788 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
4789 self.prev.as_mut().unwrap().as_rec_mut()
4790 }
4791}
4792impl<Prev: Rec> PushOpDevGetDumpReply<Prev> {
4793 pub fn new(mut prev: Prev) -> Self {
4794 Self::write_header(&mut prev);
4795 Self::new_without_header(prev)
4796 }
4797 fn new_without_header(prev: Prev) -> Self {
4798 Self {
4799 prev: Some(prev),
4800 header_offset: None,
4801 }
4802 }
4803 fn write_header(prev: &mut Prev) {
4804 let mut header = PushBuiltinNfgenmsg::new();
4805 header.set_cmd(1u8);
4806 header.set_version(1u8);
4807 prev.as_rec_mut().extend(header.as_slice());
4808 }
4809 pub fn end_nested(mut self) -> Prev {
4810 let mut prev = self.prev.take().unwrap();
4811 if let Some(header_offset) = &self.header_offset {
4812 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4813 }
4814 prev
4815 }
4816 #[doc = "netdev ifindex"]
4817 pub fn push_ifindex(mut self, value: u32) -> Self {
4818 push_header(self.as_rec_mut(), 1u16, 4 as u16);
4819 self.as_rec_mut().extend(value.to_ne_bytes());
4820 self
4821 }
4822 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4823 pub fn push_xdp_features(mut self, value: u64) -> Self {
4824 push_header(self.as_rec_mut(), 3u16, 8 as u16);
4825 self.as_rec_mut().extend(value.to_ne_bytes());
4826 self
4827 }
4828 #[doc = "max fragment count supported by ZC driver"]
4829 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
4830 push_header(self.as_rec_mut(), 4u16, 4 as u16);
4831 self.as_rec_mut().extend(value.to_ne_bytes());
4832 self
4833 }
4834 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4835 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
4836 push_header(self.as_rec_mut(), 5u16, 8 as u16);
4837 self.as_rec_mut().extend(value.to_ne_bytes());
4838 self
4839 }
4840 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4841 pub fn push_xsk_features(mut self, value: u64) -> Self {
4842 push_header(self.as_rec_mut(), 6u16, 8 as u16);
4843 self.as_rec_mut().extend(value.to_ne_bytes());
4844 self
4845 }
4846}
4847impl<Prev: Rec> Drop for PushOpDevGetDumpReply<Prev> {
4848 fn drop(&mut self) {
4849 if let Some(prev) = &mut self.prev {
4850 if let Some(header_offset) = &self.header_offset {
4851 finalize_nested_header(prev.as_rec_mut(), *header_offset);
4852 }
4853 }
4854 }
4855}
4856#[doc = "Get / dump information about a netdev."]
4857#[derive(Clone)]
4858pub enum OpDevGetDumpReply {
4859 #[doc = "netdev ifindex"]
4860 Ifindex(u32),
4861 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4862 XdpFeatures(u64),
4863 #[doc = "max fragment count supported by ZC driver"]
4864 XdpZcMaxSegs(u32),
4865 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4866 XdpRxMetadataFeatures(u64),
4867 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4868 XskFeatures(u64),
4869}
4870impl<'a> IterableOpDevGetDumpReply<'a> {
4871 #[doc = "netdev ifindex"]
4872 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
4873 let mut iter = self.clone();
4874 iter.pos = 0;
4875 for attr in iter {
4876 if let OpDevGetDumpReply::Ifindex(val) = attr? {
4877 return Ok(val);
4878 }
4879 }
4880 Err(ErrorContext::new_missing(
4881 "OpDevGetDumpReply",
4882 "Ifindex",
4883 self.orig_loc,
4884 self.buf.as_ptr() as usize,
4885 ))
4886 }
4887 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
4888 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
4889 let mut iter = self.clone();
4890 iter.pos = 0;
4891 for attr in iter {
4892 if let OpDevGetDumpReply::XdpFeatures(val) = attr? {
4893 return Ok(val);
4894 }
4895 }
4896 Err(ErrorContext::new_missing(
4897 "OpDevGetDumpReply",
4898 "XdpFeatures",
4899 self.orig_loc,
4900 self.buf.as_ptr() as usize,
4901 ))
4902 }
4903 #[doc = "max fragment count supported by ZC driver"]
4904 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
4905 let mut iter = self.clone();
4906 iter.pos = 0;
4907 for attr in iter {
4908 if let OpDevGetDumpReply::XdpZcMaxSegs(val) = attr? {
4909 return Ok(val);
4910 }
4911 }
4912 Err(ErrorContext::new_missing(
4913 "OpDevGetDumpReply",
4914 "XdpZcMaxSegs",
4915 self.orig_loc,
4916 self.buf.as_ptr() as usize,
4917 ))
4918 }
4919 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
4920 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
4921 let mut iter = self.clone();
4922 iter.pos = 0;
4923 for attr in iter {
4924 if let OpDevGetDumpReply::XdpRxMetadataFeatures(val) = attr? {
4925 return Ok(val);
4926 }
4927 }
4928 Err(ErrorContext::new_missing(
4929 "OpDevGetDumpReply",
4930 "XdpRxMetadataFeatures",
4931 self.orig_loc,
4932 self.buf.as_ptr() as usize,
4933 ))
4934 }
4935 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
4936 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
4937 let mut iter = self.clone();
4938 iter.pos = 0;
4939 for attr in iter {
4940 if let OpDevGetDumpReply::XskFeatures(val) = attr? {
4941 return Ok(val);
4942 }
4943 }
4944 Err(ErrorContext::new_missing(
4945 "OpDevGetDumpReply",
4946 "XskFeatures",
4947 self.orig_loc,
4948 self.buf.as_ptr() as usize,
4949 ))
4950 }
4951}
4952impl OpDevGetDumpReply {
4953 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDumpReply<'a> {
4954 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
4955 IterableOpDevGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
4956 }
4957 fn attr_from_type(r#type: u16) -> Option<&'static str> {
4958 Dev::attr_from_type(r#type)
4959 }
4960}
4961#[derive(Clone, Copy, Default)]
4962pub struct IterableOpDevGetDumpReply<'a> {
4963 buf: &'a [u8],
4964 pos: usize,
4965 orig_loc: usize,
4966}
4967impl<'a> IterableOpDevGetDumpReply<'a> {
4968 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
4969 Self {
4970 buf,
4971 pos: 0,
4972 orig_loc,
4973 }
4974 }
4975 pub fn get_buf(&self) -> &'a [u8] {
4976 self.buf
4977 }
4978}
4979impl<'a> Iterator for IterableOpDevGetDumpReply<'a> {
4980 type Item = Result<OpDevGetDumpReply, ErrorContext>;
4981 fn next(&mut self) -> Option<Self::Item> {
4982 if self.buf.len() == self.pos {
4983 return None;
4984 }
4985 let pos = self.pos;
4986 let mut r#type = None;
4987 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
4988 r#type = Some(header.r#type);
4989 let res = match header.r#type {
4990 1u16 => OpDevGetDumpReply::Ifindex({
4991 let res = parse_u32(next);
4992 let Some(val) = res else { break };
4993 val
4994 }),
4995 3u16 => OpDevGetDumpReply::XdpFeatures({
4996 let res = parse_u64(next);
4997 let Some(val) = res else { break };
4998 val
4999 }),
5000 4u16 => OpDevGetDumpReply::XdpZcMaxSegs({
5001 let res = parse_u32(next);
5002 let Some(val) = res else { break };
5003 val
5004 }),
5005 5u16 => OpDevGetDumpReply::XdpRxMetadataFeatures({
5006 let res = parse_u64(next);
5007 let Some(val) = res else { break };
5008 val
5009 }),
5010 6u16 => OpDevGetDumpReply::XskFeatures({
5011 let res = parse_u64(next);
5012 let Some(val) = res else { break };
5013 val
5014 }),
5015 n => {
5016 if cfg!(any(test, feature = "deny-unknown-attrs")) {
5017 break;
5018 } else {
5019 continue;
5020 }
5021 }
5022 };
5023 return Some(Ok(res));
5024 }
5025 Some(Err(ErrorContext::new(
5026 "OpDevGetDumpReply",
5027 r#type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5028 self.orig_loc,
5029 self.buf.as_ptr().wrapping_add(pos) as usize,
5030 )))
5031 }
5032}
5033impl std::fmt::Debug for IterableOpDevGetDumpReply<'_> {
5034 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5035 let mut fmt = f.debug_struct("OpDevGetDumpReply");
5036 for attr in self.clone() {
5037 let attr = match attr {
5038 Ok(a) => a,
5039 Err(err) => {
5040 fmt.finish()?;
5041 f.write_str("Err(")?;
5042 err.fmt(f)?;
5043 return f.write_str(")");
5044 }
5045 };
5046 match attr {
5047 OpDevGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
5048 OpDevGetDumpReply::XdpFeatures(val) => {
5049 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5050 }
5051 OpDevGetDumpReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5052 OpDevGetDumpReply::XdpRxMetadataFeatures(val) => fmt.field(
5053 "XdpRxMetadataFeatures",
5054 &FormatFlags(val.into(), XdpRxMetadata::from_value),
5055 ),
5056 OpDevGetDumpReply::XskFeatures(val) => fmt.field(
5057 "XskFeatures",
5058 &FormatFlags(val.into(), XskFlags::from_value),
5059 ),
5060 };
5061 }
5062 fmt.finish()
5063 }
5064}
5065impl IterableOpDevGetDumpReply<'_> {
5066 pub fn lookup_attr(
5067 &self,
5068 offset: usize,
5069 missing_type: Option<u16>,
5070 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5071 let mut stack = Vec::new();
5072 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5073 if cur == offset + PushBuiltinNfgenmsg::len() {
5074 stack.push(("OpDevGetDumpReply", offset));
5075 return (
5076 stack,
5077 missing_type.and_then(|t| OpDevGetDumpReply::attr_from_type(t)),
5078 );
5079 }
5080 if cur > offset || cur + self.buf.len() < offset {
5081 return (stack, None);
5082 }
5083 let mut attrs = self.clone();
5084 let mut last_off = cur + attrs.pos;
5085 while let Some(attr) = attrs.next() {
5086 let Ok(attr) = attr else { break };
5087 match attr {
5088 OpDevGetDumpReply::Ifindex(val) => {
5089 if last_off == offset {
5090 stack.push(("Ifindex", last_off));
5091 break;
5092 }
5093 }
5094 OpDevGetDumpReply::XdpFeatures(val) => {
5095 if last_off == offset {
5096 stack.push(("XdpFeatures", last_off));
5097 break;
5098 }
5099 }
5100 OpDevGetDumpReply::XdpZcMaxSegs(val) => {
5101 if last_off == offset {
5102 stack.push(("XdpZcMaxSegs", last_off));
5103 break;
5104 }
5105 }
5106 OpDevGetDumpReply::XdpRxMetadataFeatures(val) => {
5107 if last_off == offset {
5108 stack.push(("XdpRxMetadataFeatures", last_off));
5109 break;
5110 }
5111 }
5112 OpDevGetDumpReply::XskFeatures(val) => {
5113 if last_off == offset {
5114 stack.push(("XskFeatures", last_off));
5115 break;
5116 }
5117 }
5118 _ => {}
5119 };
5120 last_off = cur + attrs.pos;
5121 }
5122 if !stack.is_empty() {
5123 stack.push(("OpDevGetDumpReply", cur));
5124 }
5125 (stack, None)
5126 }
5127}
5128#[derive(Debug)]
5129pub struct RequestOpDevGetDumpRequest<'r> {
5130 request: Request<'r>,
5131}
5132impl<'r> RequestOpDevGetDumpRequest<'r> {
5133 pub fn new(mut request: Request<'r>) -> Self {
5134 PushOpDevGetDumpRequest::write_header(&mut request.buf_mut());
5135 Self {
5136 request: request.set_dump(),
5137 }
5138 }
5139 pub fn encode(&mut self) -> PushOpDevGetDumpRequest<&mut Vec<u8>> {
5140 PushOpDevGetDumpRequest::new_without_header(self.request.buf_mut())
5141 }
5142 pub fn into_encoder(self) -> PushOpDevGetDumpRequest<RequestBuf<'r>> {
5143 PushOpDevGetDumpRequest::new_without_header(self.request.buf)
5144 }
5145}
5146impl NetlinkRequest for RequestOpDevGetDumpRequest<'_> {
5147 type ReplyType<'buf> = IterableOpDevGetDumpReply<'buf>;
5148 fn protocol(&self) -> Protocol {
5149 Protocol::Generic("netdev".as_bytes())
5150 }
5151 fn flags(&self) -> u16 {
5152 self.request.flags
5153 }
5154 fn payload(&self) -> &[u8] {
5155 self.request.buf()
5156 }
5157 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5158 OpDevGetDumpReply::new(buf)
5159 }
5160 fn lookup(
5161 buf: &[u8],
5162 offset: usize,
5163 missing_type: Option<u16>,
5164 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5165 OpDevGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
5166 }
5167}
5168#[doc = "Get / dump information about a netdev."]
5169pub struct PushOpDevGetDoRequest<Prev: Rec> {
5170 pub(crate) prev: Option<Prev>,
5171 pub(crate) header_offset: Option<usize>,
5172}
5173impl<Prev: Rec> Rec for PushOpDevGetDoRequest<Prev> {
5174 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5175 self.prev.as_mut().unwrap().as_rec_mut()
5176 }
5177}
5178impl<Prev: Rec> PushOpDevGetDoRequest<Prev> {
5179 pub fn new(mut prev: Prev) -> Self {
5180 Self::write_header(&mut prev);
5181 Self::new_without_header(prev)
5182 }
5183 fn new_without_header(prev: Prev) -> Self {
5184 Self {
5185 prev: Some(prev),
5186 header_offset: None,
5187 }
5188 }
5189 fn write_header(prev: &mut Prev) {
5190 let mut header = PushBuiltinNfgenmsg::new();
5191 header.set_cmd(1u8);
5192 header.set_version(1u8);
5193 prev.as_rec_mut().extend(header.as_slice());
5194 }
5195 pub fn end_nested(mut self) -> Prev {
5196 let mut prev = self.prev.take().unwrap();
5197 if let Some(header_offset) = &self.header_offset {
5198 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5199 }
5200 prev
5201 }
5202 #[doc = "netdev ifindex"]
5203 pub fn push_ifindex(mut self, value: u32) -> Self {
5204 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5205 self.as_rec_mut().extend(value.to_ne_bytes());
5206 self
5207 }
5208}
5209impl<Prev: Rec> Drop for PushOpDevGetDoRequest<Prev> {
5210 fn drop(&mut self) {
5211 if let Some(prev) = &mut self.prev {
5212 if let Some(header_offset) = &self.header_offset {
5213 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5214 }
5215 }
5216 }
5217}
5218#[doc = "Get / dump information about a netdev."]
5219#[derive(Clone)]
5220pub enum OpDevGetDoRequest {
5221 #[doc = "netdev ifindex"]
5222 Ifindex(u32),
5223}
5224impl<'a> IterableOpDevGetDoRequest<'a> {
5225 #[doc = "netdev ifindex"]
5226 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5227 let mut iter = self.clone();
5228 iter.pos = 0;
5229 for attr in iter {
5230 if let OpDevGetDoRequest::Ifindex(val) = attr? {
5231 return Ok(val);
5232 }
5233 }
5234 Err(ErrorContext::new_missing(
5235 "OpDevGetDoRequest",
5236 "Ifindex",
5237 self.orig_loc,
5238 self.buf.as_ptr() as usize,
5239 ))
5240 }
5241}
5242impl OpDevGetDoRequest {
5243 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoRequest<'a> {
5244 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5245 IterableOpDevGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
5246 }
5247 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5248 Dev::attr_from_type(r#type)
5249 }
5250}
5251#[derive(Clone, Copy, Default)]
5252pub struct IterableOpDevGetDoRequest<'a> {
5253 buf: &'a [u8],
5254 pos: usize,
5255 orig_loc: usize,
5256}
5257impl<'a> IterableOpDevGetDoRequest<'a> {
5258 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5259 Self {
5260 buf,
5261 pos: 0,
5262 orig_loc,
5263 }
5264 }
5265 pub fn get_buf(&self) -> &'a [u8] {
5266 self.buf
5267 }
5268}
5269impl<'a> Iterator for IterableOpDevGetDoRequest<'a> {
5270 type Item = Result<OpDevGetDoRequest, ErrorContext>;
5271 fn next(&mut self) -> Option<Self::Item> {
5272 if self.buf.len() == self.pos {
5273 return None;
5274 }
5275 let pos = self.pos;
5276 let mut r#type = None;
5277 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5278 r#type = Some(header.r#type);
5279 let res = match header.r#type {
5280 1u16 => OpDevGetDoRequest::Ifindex({
5281 let res = parse_u32(next);
5282 let Some(val) = res else { break };
5283 val
5284 }),
5285 n => {
5286 if cfg!(any(test, feature = "deny-unknown-attrs")) {
5287 break;
5288 } else {
5289 continue;
5290 }
5291 }
5292 };
5293 return Some(Ok(res));
5294 }
5295 Some(Err(ErrorContext::new(
5296 "OpDevGetDoRequest",
5297 r#type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5298 self.orig_loc,
5299 self.buf.as_ptr().wrapping_add(pos) as usize,
5300 )))
5301 }
5302}
5303impl std::fmt::Debug for IterableOpDevGetDoRequest<'_> {
5304 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5305 let mut fmt = f.debug_struct("OpDevGetDoRequest");
5306 for attr in self.clone() {
5307 let attr = match attr {
5308 Ok(a) => a,
5309 Err(err) => {
5310 fmt.finish()?;
5311 f.write_str("Err(")?;
5312 err.fmt(f)?;
5313 return f.write_str(")");
5314 }
5315 };
5316 match attr {
5317 OpDevGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
5318 };
5319 }
5320 fmt.finish()
5321 }
5322}
5323impl IterableOpDevGetDoRequest<'_> {
5324 pub fn lookup_attr(
5325 &self,
5326 offset: usize,
5327 missing_type: Option<u16>,
5328 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5329 let mut stack = Vec::new();
5330 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5331 if cur == offset + PushBuiltinNfgenmsg::len() {
5332 stack.push(("OpDevGetDoRequest", offset));
5333 return (
5334 stack,
5335 missing_type.and_then(|t| OpDevGetDoRequest::attr_from_type(t)),
5336 );
5337 }
5338 if cur > offset || cur + self.buf.len() < offset {
5339 return (stack, None);
5340 }
5341 let mut attrs = self.clone();
5342 let mut last_off = cur + attrs.pos;
5343 while let Some(attr) = attrs.next() {
5344 let Ok(attr) = attr else { break };
5345 match attr {
5346 OpDevGetDoRequest::Ifindex(val) => {
5347 if last_off == offset {
5348 stack.push(("Ifindex", last_off));
5349 break;
5350 }
5351 }
5352 _ => {}
5353 };
5354 last_off = cur + attrs.pos;
5355 }
5356 if !stack.is_empty() {
5357 stack.push(("OpDevGetDoRequest", cur));
5358 }
5359 (stack, None)
5360 }
5361}
5362#[doc = "Get / dump information about a netdev."]
5363pub struct PushOpDevGetDoReply<Prev: Rec> {
5364 pub(crate) prev: Option<Prev>,
5365 pub(crate) header_offset: Option<usize>,
5366}
5367impl<Prev: Rec> Rec for PushOpDevGetDoReply<Prev> {
5368 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5369 self.prev.as_mut().unwrap().as_rec_mut()
5370 }
5371}
5372impl<Prev: Rec> PushOpDevGetDoReply<Prev> {
5373 pub fn new(mut prev: Prev) -> Self {
5374 Self::write_header(&mut prev);
5375 Self::new_without_header(prev)
5376 }
5377 fn new_without_header(prev: Prev) -> Self {
5378 Self {
5379 prev: Some(prev),
5380 header_offset: None,
5381 }
5382 }
5383 fn write_header(prev: &mut Prev) {
5384 let mut header = PushBuiltinNfgenmsg::new();
5385 header.set_cmd(1u8);
5386 header.set_version(1u8);
5387 prev.as_rec_mut().extend(header.as_slice());
5388 }
5389 pub fn end_nested(mut self) -> Prev {
5390 let mut prev = self.prev.take().unwrap();
5391 if let Some(header_offset) = &self.header_offset {
5392 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5393 }
5394 prev
5395 }
5396 #[doc = "netdev ifindex"]
5397 pub fn push_ifindex(mut self, value: u32) -> Self {
5398 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5399 self.as_rec_mut().extend(value.to_ne_bytes());
5400 self
5401 }
5402 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5403 pub fn push_xdp_features(mut self, value: u64) -> Self {
5404 push_header(self.as_rec_mut(), 3u16, 8 as u16);
5405 self.as_rec_mut().extend(value.to_ne_bytes());
5406 self
5407 }
5408 #[doc = "max fragment count supported by ZC driver"]
5409 pub fn push_xdp_zc_max_segs(mut self, value: u32) -> Self {
5410 push_header(self.as_rec_mut(), 4u16, 4 as u16);
5411 self.as_rec_mut().extend(value.to_ne_bytes());
5412 self
5413 }
5414 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5415 pub fn push_xdp_rx_metadata_features(mut self, value: u64) -> Self {
5416 push_header(self.as_rec_mut(), 5u16, 8 as u16);
5417 self.as_rec_mut().extend(value.to_ne_bytes());
5418 self
5419 }
5420 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5421 pub fn push_xsk_features(mut self, value: u64) -> Self {
5422 push_header(self.as_rec_mut(), 6u16, 8 as u16);
5423 self.as_rec_mut().extend(value.to_ne_bytes());
5424 self
5425 }
5426}
5427impl<Prev: Rec> Drop for PushOpDevGetDoReply<Prev> {
5428 fn drop(&mut self) {
5429 if let Some(prev) = &mut self.prev {
5430 if let Some(header_offset) = &self.header_offset {
5431 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5432 }
5433 }
5434 }
5435}
5436#[doc = "Get / dump information about a netdev."]
5437#[derive(Clone)]
5438pub enum OpDevGetDoReply {
5439 #[doc = "netdev ifindex"]
5440 Ifindex(u32),
5441 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5442 XdpFeatures(u64),
5443 #[doc = "max fragment count supported by ZC driver"]
5444 XdpZcMaxSegs(u32),
5445 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5446 XdpRxMetadataFeatures(u64),
5447 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5448 XskFeatures(u64),
5449}
5450impl<'a> IterableOpDevGetDoReply<'a> {
5451 #[doc = "netdev ifindex"]
5452 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
5453 let mut iter = self.clone();
5454 iter.pos = 0;
5455 for attr in iter {
5456 if let OpDevGetDoReply::Ifindex(val) = attr? {
5457 return Ok(val);
5458 }
5459 }
5460 Err(ErrorContext::new_missing(
5461 "OpDevGetDoReply",
5462 "Ifindex",
5463 self.orig_loc,
5464 self.buf.as_ptr() as usize,
5465 ))
5466 }
5467 #[doc = "Bitmask of enabled xdp-features.\nAssociated type: \"XdpAct\" (enum)"]
5468 pub fn get_xdp_features(&self) -> Result<u64, ErrorContext> {
5469 let mut iter = self.clone();
5470 iter.pos = 0;
5471 for attr in iter {
5472 if let OpDevGetDoReply::XdpFeatures(val) = attr? {
5473 return Ok(val);
5474 }
5475 }
5476 Err(ErrorContext::new_missing(
5477 "OpDevGetDoReply",
5478 "XdpFeatures",
5479 self.orig_loc,
5480 self.buf.as_ptr() as usize,
5481 ))
5482 }
5483 #[doc = "max fragment count supported by ZC driver"]
5484 pub fn get_xdp_zc_max_segs(&self) -> Result<u32, ErrorContext> {
5485 let mut iter = self.clone();
5486 iter.pos = 0;
5487 for attr in iter {
5488 if let OpDevGetDoReply::XdpZcMaxSegs(val) = attr? {
5489 return Ok(val);
5490 }
5491 }
5492 Err(ErrorContext::new_missing(
5493 "OpDevGetDoReply",
5494 "XdpZcMaxSegs",
5495 self.orig_loc,
5496 self.buf.as_ptr() as usize,
5497 ))
5498 }
5499 #[doc = "Bitmask of supported XDP receive metadata features. See Documentation/networking/xdp-rx-metadata.rst for more details.\nAssociated type: \"XdpRxMetadata\" (enum)"]
5500 pub fn get_xdp_rx_metadata_features(&self) -> Result<u64, ErrorContext> {
5501 let mut iter = self.clone();
5502 iter.pos = 0;
5503 for attr in iter {
5504 if let OpDevGetDoReply::XdpRxMetadataFeatures(val) = attr? {
5505 return Ok(val);
5506 }
5507 }
5508 Err(ErrorContext::new_missing(
5509 "OpDevGetDoReply",
5510 "XdpRxMetadataFeatures",
5511 self.orig_loc,
5512 self.buf.as_ptr() as usize,
5513 ))
5514 }
5515 #[doc = "Bitmask of enabled AF_XDP features.\nAssociated type: \"XskFlags\" (enum)"]
5516 pub fn get_xsk_features(&self) -> Result<u64, ErrorContext> {
5517 let mut iter = self.clone();
5518 iter.pos = 0;
5519 for attr in iter {
5520 if let OpDevGetDoReply::XskFeatures(val) = attr? {
5521 return Ok(val);
5522 }
5523 }
5524 Err(ErrorContext::new_missing(
5525 "OpDevGetDoReply",
5526 "XskFeatures",
5527 self.orig_loc,
5528 self.buf.as_ptr() as usize,
5529 ))
5530 }
5531}
5532impl OpDevGetDoReply {
5533 pub fn new<'a>(buf: &'a [u8]) -> IterableOpDevGetDoReply<'a> {
5534 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5535 IterableOpDevGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
5536 }
5537 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5538 Dev::attr_from_type(r#type)
5539 }
5540}
5541#[derive(Clone, Copy, Default)]
5542pub struct IterableOpDevGetDoReply<'a> {
5543 buf: &'a [u8],
5544 pos: usize,
5545 orig_loc: usize,
5546}
5547impl<'a> IterableOpDevGetDoReply<'a> {
5548 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5549 Self {
5550 buf,
5551 pos: 0,
5552 orig_loc,
5553 }
5554 }
5555 pub fn get_buf(&self) -> &'a [u8] {
5556 self.buf
5557 }
5558}
5559impl<'a> Iterator for IterableOpDevGetDoReply<'a> {
5560 type Item = Result<OpDevGetDoReply, ErrorContext>;
5561 fn next(&mut self) -> Option<Self::Item> {
5562 if self.buf.len() == self.pos {
5563 return None;
5564 }
5565 let pos = self.pos;
5566 let mut r#type = None;
5567 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5568 r#type = Some(header.r#type);
5569 let res = match header.r#type {
5570 1u16 => OpDevGetDoReply::Ifindex({
5571 let res = parse_u32(next);
5572 let Some(val) = res else { break };
5573 val
5574 }),
5575 3u16 => OpDevGetDoReply::XdpFeatures({
5576 let res = parse_u64(next);
5577 let Some(val) = res else { break };
5578 val
5579 }),
5580 4u16 => OpDevGetDoReply::XdpZcMaxSegs({
5581 let res = parse_u32(next);
5582 let Some(val) = res else { break };
5583 val
5584 }),
5585 5u16 => OpDevGetDoReply::XdpRxMetadataFeatures({
5586 let res = parse_u64(next);
5587 let Some(val) = res else { break };
5588 val
5589 }),
5590 6u16 => OpDevGetDoReply::XskFeatures({
5591 let res = parse_u64(next);
5592 let Some(val) = res else { break };
5593 val
5594 }),
5595 n => {
5596 if cfg!(any(test, feature = "deny-unknown-attrs")) {
5597 break;
5598 } else {
5599 continue;
5600 }
5601 }
5602 };
5603 return Some(Ok(res));
5604 }
5605 Some(Err(ErrorContext::new(
5606 "OpDevGetDoReply",
5607 r#type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5608 self.orig_loc,
5609 self.buf.as_ptr().wrapping_add(pos) as usize,
5610 )))
5611 }
5612}
5613impl std::fmt::Debug for IterableOpDevGetDoReply<'_> {
5614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5615 let mut fmt = f.debug_struct("OpDevGetDoReply");
5616 for attr in self.clone() {
5617 let attr = match attr {
5618 Ok(a) => a,
5619 Err(err) => {
5620 fmt.finish()?;
5621 f.write_str("Err(")?;
5622 err.fmt(f)?;
5623 return f.write_str(")");
5624 }
5625 };
5626 match attr {
5627 OpDevGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
5628 OpDevGetDoReply::XdpFeatures(val) => {
5629 fmt.field("XdpFeatures", &FormatFlags(val.into(), XdpAct::from_value))
5630 }
5631 OpDevGetDoReply::XdpZcMaxSegs(val) => fmt.field("XdpZcMaxSegs", &val),
5632 OpDevGetDoReply::XdpRxMetadataFeatures(val) => fmt.field(
5633 "XdpRxMetadataFeatures",
5634 &FormatFlags(val.into(), XdpRxMetadata::from_value),
5635 ),
5636 OpDevGetDoReply::XskFeatures(val) => fmt.field(
5637 "XskFeatures",
5638 &FormatFlags(val.into(), XskFlags::from_value),
5639 ),
5640 };
5641 }
5642 fmt.finish()
5643 }
5644}
5645impl IterableOpDevGetDoReply<'_> {
5646 pub fn lookup_attr(
5647 &self,
5648 offset: usize,
5649 missing_type: Option<u16>,
5650 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5651 let mut stack = Vec::new();
5652 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5653 if cur == offset + PushBuiltinNfgenmsg::len() {
5654 stack.push(("OpDevGetDoReply", offset));
5655 return (
5656 stack,
5657 missing_type.and_then(|t| OpDevGetDoReply::attr_from_type(t)),
5658 );
5659 }
5660 if cur > offset || cur + self.buf.len() < offset {
5661 return (stack, None);
5662 }
5663 let mut attrs = self.clone();
5664 let mut last_off = cur + attrs.pos;
5665 while let Some(attr) = attrs.next() {
5666 let Ok(attr) = attr else { break };
5667 match attr {
5668 OpDevGetDoReply::Ifindex(val) => {
5669 if last_off == offset {
5670 stack.push(("Ifindex", last_off));
5671 break;
5672 }
5673 }
5674 OpDevGetDoReply::XdpFeatures(val) => {
5675 if last_off == offset {
5676 stack.push(("XdpFeatures", last_off));
5677 break;
5678 }
5679 }
5680 OpDevGetDoReply::XdpZcMaxSegs(val) => {
5681 if last_off == offset {
5682 stack.push(("XdpZcMaxSegs", last_off));
5683 break;
5684 }
5685 }
5686 OpDevGetDoReply::XdpRxMetadataFeatures(val) => {
5687 if last_off == offset {
5688 stack.push(("XdpRxMetadataFeatures", last_off));
5689 break;
5690 }
5691 }
5692 OpDevGetDoReply::XskFeatures(val) => {
5693 if last_off == offset {
5694 stack.push(("XskFeatures", last_off));
5695 break;
5696 }
5697 }
5698 _ => {}
5699 };
5700 last_off = cur + attrs.pos;
5701 }
5702 if !stack.is_empty() {
5703 stack.push(("OpDevGetDoReply", cur));
5704 }
5705 (stack, None)
5706 }
5707}
5708#[derive(Debug)]
5709pub struct RequestOpDevGetDoRequest<'r> {
5710 request: Request<'r>,
5711}
5712impl<'r> RequestOpDevGetDoRequest<'r> {
5713 pub fn new(mut request: Request<'r>) -> Self {
5714 PushOpDevGetDoRequest::write_header(&mut request.buf_mut());
5715 Self { request: request }
5716 }
5717 pub fn encode(&mut self) -> PushOpDevGetDoRequest<&mut Vec<u8>> {
5718 PushOpDevGetDoRequest::new_without_header(self.request.buf_mut())
5719 }
5720 pub fn into_encoder(self) -> PushOpDevGetDoRequest<RequestBuf<'r>> {
5721 PushOpDevGetDoRequest::new_without_header(self.request.buf)
5722 }
5723}
5724impl NetlinkRequest for RequestOpDevGetDoRequest<'_> {
5725 type ReplyType<'buf> = IterableOpDevGetDoReply<'buf>;
5726 fn protocol(&self) -> Protocol {
5727 Protocol::Generic("netdev".as_bytes())
5728 }
5729 fn flags(&self) -> u16 {
5730 self.request.flags
5731 }
5732 fn payload(&self) -> &[u8] {
5733 self.request.buf()
5734 }
5735 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
5736 OpDevGetDoReply::new(buf)
5737 }
5738 fn lookup(
5739 buf: &[u8],
5740 offset: usize,
5741 missing_type: Option<u16>,
5742 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5743 OpDevGetDoRequest::new(buf).lookup_attr(offset, missing_type)
5744 }
5745}
5746#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5747pub struct PushOpPagePoolGetDumpRequest<Prev: Rec> {
5748 pub(crate) prev: Option<Prev>,
5749 pub(crate) header_offset: Option<usize>,
5750}
5751impl<Prev: Rec> Rec for PushOpPagePoolGetDumpRequest<Prev> {
5752 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5753 self.prev.as_mut().unwrap().as_rec_mut()
5754 }
5755}
5756impl<Prev: Rec> PushOpPagePoolGetDumpRequest<Prev> {
5757 pub fn new(mut prev: Prev) -> Self {
5758 Self::write_header(&mut prev);
5759 Self::new_without_header(prev)
5760 }
5761 fn new_without_header(prev: Prev) -> Self {
5762 Self {
5763 prev: Some(prev),
5764 header_offset: None,
5765 }
5766 }
5767 fn write_header(prev: &mut Prev) {
5768 let mut header = PushBuiltinNfgenmsg::new();
5769 header.set_cmd(5u8);
5770 header.set_version(1u8);
5771 prev.as_rec_mut().extend(header.as_slice());
5772 }
5773 pub fn end_nested(mut self) -> Prev {
5774 let mut prev = self.prev.take().unwrap();
5775 if let Some(header_offset) = &self.header_offset {
5776 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5777 }
5778 prev
5779 }
5780}
5781impl<Prev: Rec> Drop for PushOpPagePoolGetDumpRequest<Prev> {
5782 fn drop(&mut self) {
5783 if let Some(prev) = &mut self.prev {
5784 if let Some(header_offset) = &self.header_offset {
5785 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5786 }
5787 }
5788 }
5789}
5790#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5791#[derive(Clone)]
5792pub enum OpPagePoolGetDumpRequest {}
5793impl<'a> IterableOpPagePoolGetDumpRequest<'a> {}
5794impl OpPagePoolGetDumpRequest {
5795 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpRequest<'a> {
5796 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
5797 IterableOpPagePoolGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
5798 }
5799 fn attr_from_type(r#type: u16) -> Option<&'static str> {
5800 PagePool::attr_from_type(r#type)
5801 }
5802}
5803#[derive(Clone, Copy, Default)]
5804pub struct IterableOpPagePoolGetDumpRequest<'a> {
5805 buf: &'a [u8],
5806 pos: usize,
5807 orig_loc: usize,
5808}
5809impl<'a> IterableOpPagePoolGetDumpRequest<'a> {
5810 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
5811 Self {
5812 buf,
5813 pos: 0,
5814 orig_loc,
5815 }
5816 }
5817 pub fn get_buf(&self) -> &'a [u8] {
5818 self.buf
5819 }
5820}
5821impl<'a> Iterator for IterableOpPagePoolGetDumpRequest<'a> {
5822 type Item = Result<OpPagePoolGetDumpRequest, ErrorContext>;
5823 fn next(&mut self) -> Option<Self::Item> {
5824 if self.buf.len() == self.pos {
5825 return None;
5826 }
5827 let pos = self.pos;
5828 let mut r#type = None;
5829 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
5830 r#type = Some(header.r#type);
5831 let res = match header.r#type {
5832 n => {
5833 if cfg!(any(test, feature = "deny-unknown-attrs")) {
5834 break;
5835 } else {
5836 continue;
5837 }
5838 }
5839 };
5840 return Some(Ok(res));
5841 }
5842 Some(Err(ErrorContext::new(
5843 "OpPagePoolGetDumpRequest",
5844 r#type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5845 self.orig_loc,
5846 self.buf.as_ptr().wrapping_add(pos) as usize,
5847 )))
5848 }
5849}
5850impl std::fmt::Debug for IterableOpPagePoolGetDumpRequest<'_> {
5851 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5852 let mut fmt = f.debug_struct("OpPagePoolGetDumpRequest");
5853 for attr in self.clone() {
5854 let attr = match attr {
5855 Ok(a) => a,
5856 Err(err) => {
5857 fmt.finish()?;
5858 f.write_str("Err(")?;
5859 err.fmt(f)?;
5860 return f.write_str(")");
5861 }
5862 };
5863 match attr {};
5864 }
5865 fmt.finish()
5866 }
5867}
5868impl IterableOpPagePoolGetDumpRequest<'_> {
5869 pub fn lookup_attr(
5870 &self,
5871 offset: usize,
5872 missing_type: Option<u16>,
5873 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
5874 let mut stack = Vec::new();
5875 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
5876 if cur == offset + PushBuiltinNfgenmsg::len() {
5877 stack.push(("OpPagePoolGetDumpRequest", offset));
5878 return (
5879 stack,
5880 missing_type.and_then(|t| OpPagePoolGetDumpRequest::attr_from_type(t)),
5881 );
5882 }
5883 (stack, None)
5884 }
5885}
5886#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5887pub struct PushOpPagePoolGetDumpReply<Prev: Rec> {
5888 pub(crate) prev: Option<Prev>,
5889 pub(crate) header_offset: Option<usize>,
5890}
5891impl<Prev: Rec> Rec for PushOpPagePoolGetDumpReply<Prev> {
5892 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
5893 self.prev.as_mut().unwrap().as_rec_mut()
5894 }
5895}
5896impl<Prev: Rec> PushOpPagePoolGetDumpReply<Prev> {
5897 pub fn new(mut prev: Prev) -> Self {
5898 Self::write_header(&mut prev);
5899 Self::new_without_header(prev)
5900 }
5901 fn new_without_header(prev: Prev) -> Self {
5902 Self {
5903 prev: Some(prev),
5904 header_offset: None,
5905 }
5906 }
5907 fn write_header(prev: &mut Prev) {
5908 let mut header = PushBuiltinNfgenmsg::new();
5909 header.set_cmd(5u8);
5910 header.set_version(1u8);
5911 prev.as_rec_mut().extend(header.as_slice());
5912 }
5913 pub fn end_nested(mut self) -> Prev {
5914 let mut prev = self.prev.take().unwrap();
5915 if let Some(header_offset) = &self.header_offset {
5916 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5917 }
5918 prev
5919 }
5920 #[doc = "Unique ID of a Page Pool instance."]
5921 pub fn push_id(mut self, value: u32) -> Self {
5922 push_header(self.as_rec_mut(), 1u16, 4 as u16);
5923 self.as_rec_mut().extend(value.to_ne_bytes());
5924 self
5925 }
5926 #[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"]
5927 pub fn push_ifindex(mut self, value: u32) -> Self {
5928 push_header(self.as_rec_mut(), 2u16, 4 as u16);
5929 self.as_rec_mut().extend(value.to_ne_bytes());
5930 self
5931 }
5932 #[doc = "Id of NAPI using this Page Pool instance."]
5933 pub fn push_napi_id(mut self, value: u32) -> Self {
5934 push_header(self.as_rec_mut(), 3u16, 4 as u16);
5935 self.as_rec_mut().extend(value.to_ne_bytes());
5936 self
5937 }
5938 #[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"]
5939 pub fn push_inflight(mut self, value: u32) -> Self {
5940 push_header(self.as_rec_mut(), 4u16, 4 as u16);
5941 self.as_rec_mut().extend(value.to_ne_bytes());
5942 self
5943 }
5944 #[doc = "Amount of memory held by inflight pages.\n"]
5945 pub fn push_inflight_mem(mut self, value: u32) -> Self {
5946 push_header(self.as_rec_mut(), 5u16, 4 as u16);
5947 self.as_rec_mut().extend(value.to_ne_bytes());
5948 self
5949 }
5950 #[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"]
5951 pub fn push_detach_time(mut self, value: u32) -> Self {
5952 push_header(self.as_rec_mut(), 6u16, 4 as u16);
5953 self.as_rec_mut().extend(value.to_ne_bytes());
5954 self
5955 }
5956 #[doc = "ID of the dmabuf this page-pool is attached to."]
5957 pub fn push_dmabuf(mut self, value: u32) -> Self {
5958 push_header(self.as_rec_mut(), 7u16, 4 as u16);
5959 self.as_rec_mut().extend(value.to_ne_bytes());
5960 self
5961 }
5962 #[doc = "io-uring memory provider information."]
5963 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
5964 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
5965 PushIoUringProviderInfo {
5966 prev: Some(self),
5967 header_offset: Some(header_offset),
5968 }
5969 }
5970}
5971impl<Prev: Rec> Drop for PushOpPagePoolGetDumpReply<Prev> {
5972 fn drop(&mut self) {
5973 if let Some(prev) = &mut self.prev {
5974 if let Some(header_offset) = &self.header_offset {
5975 finalize_nested_header(prev.as_rec_mut(), *header_offset);
5976 }
5977 }
5978 }
5979}
5980#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
5981#[derive(Clone)]
5982pub enum OpPagePoolGetDumpReply<'a> {
5983 #[doc = "Unique ID of a Page Pool instance."]
5984 Id(u32),
5985 #[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"]
5986 Ifindex(u32),
5987 #[doc = "Id of NAPI using this Page Pool instance."]
5988 NapiId(u32),
5989 #[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"]
5990 Inflight(u32),
5991 #[doc = "Amount of memory held by inflight pages.\n"]
5992 InflightMem(u32),
5993 #[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"]
5994 DetachTime(u32),
5995 #[doc = "ID of the dmabuf this page-pool is attached to."]
5996 Dmabuf(u32),
5997 #[doc = "io-uring memory provider information."]
5998 IoUring(IterableIoUringProviderInfo<'a>),
5999}
6000impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6001 #[doc = "Unique ID of a Page Pool instance."]
6002 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6003 let mut iter = self.clone();
6004 iter.pos = 0;
6005 for attr in iter {
6006 if let OpPagePoolGetDumpReply::Id(val) = attr? {
6007 return Ok(val);
6008 }
6009 }
6010 Err(ErrorContext::new_missing(
6011 "OpPagePoolGetDumpReply",
6012 "Id",
6013 self.orig_loc,
6014 self.buf.as_ptr() as usize,
6015 ))
6016 }
6017 #[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"]
6018 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6019 let mut iter = self.clone();
6020 iter.pos = 0;
6021 for attr in iter {
6022 if let OpPagePoolGetDumpReply::Ifindex(val) = attr? {
6023 return Ok(val);
6024 }
6025 }
6026 Err(ErrorContext::new_missing(
6027 "OpPagePoolGetDumpReply",
6028 "Ifindex",
6029 self.orig_loc,
6030 self.buf.as_ptr() as usize,
6031 ))
6032 }
6033 #[doc = "Id of NAPI using this Page Pool instance."]
6034 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6035 let mut iter = self.clone();
6036 iter.pos = 0;
6037 for attr in iter {
6038 if let OpPagePoolGetDumpReply::NapiId(val) = attr? {
6039 return Ok(val);
6040 }
6041 }
6042 Err(ErrorContext::new_missing(
6043 "OpPagePoolGetDumpReply",
6044 "NapiId",
6045 self.orig_loc,
6046 self.buf.as_ptr() as usize,
6047 ))
6048 }
6049 #[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"]
6050 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6051 let mut iter = self.clone();
6052 iter.pos = 0;
6053 for attr in iter {
6054 if let OpPagePoolGetDumpReply::Inflight(val) = attr? {
6055 return Ok(val);
6056 }
6057 }
6058 Err(ErrorContext::new_missing(
6059 "OpPagePoolGetDumpReply",
6060 "Inflight",
6061 self.orig_loc,
6062 self.buf.as_ptr() as usize,
6063 ))
6064 }
6065 #[doc = "Amount of memory held by inflight pages.\n"]
6066 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6067 let mut iter = self.clone();
6068 iter.pos = 0;
6069 for attr in iter {
6070 if let OpPagePoolGetDumpReply::InflightMem(val) = attr? {
6071 return Ok(val);
6072 }
6073 }
6074 Err(ErrorContext::new_missing(
6075 "OpPagePoolGetDumpReply",
6076 "InflightMem",
6077 self.orig_loc,
6078 self.buf.as_ptr() as usize,
6079 ))
6080 }
6081 #[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"]
6082 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6083 let mut iter = self.clone();
6084 iter.pos = 0;
6085 for attr in iter {
6086 if let OpPagePoolGetDumpReply::DetachTime(val) = attr? {
6087 return Ok(val);
6088 }
6089 }
6090 Err(ErrorContext::new_missing(
6091 "OpPagePoolGetDumpReply",
6092 "DetachTime",
6093 self.orig_loc,
6094 self.buf.as_ptr() as usize,
6095 ))
6096 }
6097 #[doc = "ID of the dmabuf this page-pool is attached to."]
6098 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6099 let mut iter = self.clone();
6100 iter.pos = 0;
6101 for attr in iter {
6102 if let OpPagePoolGetDumpReply::Dmabuf(val) = attr? {
6103 return Ok(val);
6104 }
6105 }
6106 Err(ErrorContext::new_missing(
6107 "OpPagePoolGetDumpReply",
6108 "Dmabuf",
6109 self.orig_loc,
6110 self.buf.as_ptr() as usize,
6111 ))
6112 }
6113 #[doc = "io-uring memory provider information."]
6114 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6115 let mut iter = self.clone();
6116 iter.pos = 0;
6117 for attr in iter {
6118 if let OpPagePoolGetDumpReply::IoUring(val) = attr? {
6119 return Ok(val);
6120 }
6121 }
6122 Err(ErrorContext::new_missing(
6123 "OpPagePoolGetDumpReply",
6124 "IoUring",
6125 self.orig_loc,
6126 self.buf.as_ptr() as usize,
6127 ))
6128 }
6129}
6130impl OpPagePoolGetDumpReply<'_> {
6131 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDumpReply<'a> {
6132 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6133 IterableOpPagePoolGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
6134 }
6135 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6136 PagePool::attr_from_type(r#type)
6137 }
6138}
6139#[derive(Clone, Copy, Default)]
6140pub struct IterableOpPagePoolGetDumpReply<'a> {
6141 buf: &'a [u8],
6142 pos: usize,
6143 orig_loc: usize,
6144}
6145impl<'a> IterableOpPagePoolGetDumpReply<'a> {
6146 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6147 Self {
6148 buf,
6149 pos: 0,
6150 orig_loc,
6151 }
6152 }
6153 pub fn get_buf(&self) -> &'a [u8] {
6154 self.buf
6155 }
6156}
6157impl<'a> Iterator for IterableOpPagePoolGetDumpReply<'a> {
6158 type Item = Result<OpPagePoolGetDumpReply<'a>, ErrorContext>;
6159 fn next(&mut self) -> Option<Self::Item> {
6160 if self.buf.len() == self.pos {
6161 return None;
6162 }
6163 let pos = self.pos;
6164 let mut r#type = None;
6165 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6166 r#type = Some(header.r#type);
6167 let res = match header.r#type {
6168 1u16 => OpPagePoolGetDumpReply::Id({
6169 let res = parse_u32(next);
6170 let Some(val) = res else { break };
6171 val
6172 }),
6173 2u16 => OpPagePoolGetDumpReply::Ifindex({
6174 let res = parse_u32(next);
6175 let Some(val) = res else { break };
6176 val
6177 }),
6178 3u16 => OpPagePoolGetDumpReply::NapiId({
6179 let res = parse_u32(next);
6180 let Some(val) = res else { break };
6181 val
6182 }),
6183 4u16 => OpPagePoolGetDumpReply::Inflight({
6184 let res = parse_u32(next);
6185 let Some(val) = res else { break };
6186 val
6187 }),
6188 5u16 => OpPagePoolGetDumpReply::InflightMem({
6189 let res = parse_u32(next);
6190 let Some(val) = res else { break };
6191 val
6192 }),
6193 6u16 => OpPagePoolGetDumpReply::DetachTime({
6194 let res = parse_u32(next);
6195 let Some(val) = res else { break };
6196 val
6197 }),
6198 7u16 => OpPagePoolGetDumpReply::Dmabuf({
6199 let res = parse_u32(next);
6200 let Some(val) = res else { break };
6201 val
6202 }),
6203 8u16 => OpPagePoolGetDumpReply::IoUring({
6204 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6205 let Some(val) = res else { break };
6206 val
6207 }),
6208 n => {
6209 if cfg!(any(test, feature = "deny-unknown-attrs")) {
6210 break;
6211 } else {
6212 continue;
6213 }
6214 }
6215 };
6216 return Some(Ok(res));
6217 }
6218 Some(Err(ErrorContext::new(
6219 "OpPagePoolGetDumpReply",
6220 r#type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6221 self.orig_loc,
6222 self.buf.as_ptr().wrapping_add(pos) as usize,
6223 )))
6224 }
6225}
6226impl<'a> std::fmt::Debug for IterableOpPagePoolGetDumpReply<'_> {
6227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6228 let mut fmt = f.debug_struct("OpPagePoolGetDumpReply");
6229 for attr in self.clone() {
6230 let attr = match attr {
6231 Ok(a) => a,
6232 Err(err) => {
6233 fmt.finish()?;
6234 f.write_str("Err(")?;
6235 err.fmt(f)?;
6236 return f.write_str(")");
6237 }
6238 };
6239 match attr {
6240 OpPagePoolGetDumpReply::Id(val) => fmt.field("Id", &val),
6241 OpPagePoolGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
6242 OpPagePoolGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
6243 OpPagePoolGetDumpReply::Inflight(val) => fmt.field("Inflight", &val),
6244 OpPagePoolGetDumpReply::InflightMem(val) => fmt.field("InflightMem", &val),
6245 OpPagePoolGetDumpReply::DetachTime(val) => fmt.field("DetachTime", &val),
6246 OpPagePoolGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6247 OpPagePoolGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
6248 };
6249 }
6250 fmt.finish()
6251 }
6252}
6253impl IterableOpPagePoolGetDumpReply<'_> {
6254 pub fn lookup_attr(
6255 &self,
6256 offset: usize,
6257 missing_type: Option<u16>,
6258 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6259 let mut stack = Vec::new();
6260 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6261 if cur == offset + PushBuiltinNfgenmsg::len() {
6262 stack.push(("OpPagePoolGetDumpReply", offset));
6263 return (
6264 stack,
6265 missing_type.and_then(|t| OpPagePoolGetDumpReply::attr_from_type(t)),
6266 );
6267 }
6268 if cur > offset || cur + self.buf.len() < offset {
6269 return (stack, None);
6270 }
6271 let mut attrs = self.clone();
6272 let mut last_off = cur + attrs.pos;
6273 let mut missing = None;
6274 while let Some(attr) = attrs.next() {
6275 let Ok(attr) = attr else { break };
6276 match attr {
6277 OpPagePoolGetDumpReply::Id(val) => {
6278 if last_off == offset {
6279 stack.push(("Id", last_off));
6280 break;
6281 }
6282 }
6283 OpPagePoolGetDumpReply::Ifindex(val) => {
6284 if last_off == offset {
6285 stack.push(("Ifindex", last_off));
6286 break;
6287 }
6288 }
6289 OpPagePoolGetDumpReply::NapiId(val) => {
6290 if last_off == offset {
6291 stack.push(("NapiId", last_off));
6292 break;
6293 }
6294 }
6295 OpPagePoolGetDumpReply::Inflight(val) => {
6296 if last_off == offset {
6297 stack.push(("Inflight", last_off));
6298 break;
6299 }
6300 }
6301 OpPagePoolGetDumpReply::InflightMem(val) => {
6302 if last_off == offset {
6303 stack.push(("InflightMem", last_off));
6304 break;
6305 }
6306 }
6307 OpPagePoolGetDumpReply::DetachTime(val) => {
6308 if last_off == offset {
6309 stack.push(("DetachTime", last_off));
6310 break;
6311 }
6312 }
6313 OpPagePoolGetDumpReply::Dmabuf(val) => {
6314 if last_off == offset {
6315 stack.push(("Dmabuf", last_off));
6316 break;
6317 }
6318 }
6319 OpPagePoolGetDumpReply::IoUring(val) => {
6320 (stack, missing) = val.lookup_attr(offset, missing_type);
6321 if !stack.is_empty() {
6322 break;
6323 }
6324 }
6325 _ => {}
6326 };
6327 last_off = cur + attrs.pos;
6328 }
6329 if !stack.is_empty() {
6330 stack.push(("OpPagePoolGetDumpReply", cur));
6331 }
6332 (stack, missing)
6333 }
6334}
6335#[derive(Debug)]
6336pub struct RequestOpPagePoolGetDumpRequest<'r> {
6337 request: Request<'r>,
6338}
6339impl<'r> RequestOpPagePoolGetDumpRequest<'r> {
6340 pub fn new(mut request: Request<'r>) -> Self {
6341 PushOpPagePoolGetDumpRequest::write_header(&mut request.buf_mut());
6342 Self {
6343 request: request.set_dump(),
6344 }
6345 }
6346 pub fn encode(&mut self) -> PushOpPagePoolGetDumpRequest<&mut Vec<u8>> {
6347 PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf_mut())
6348 }
6349 pub fn into_encoder(self) -> PushOpPagePoolGetDumpRequest<RequestBuf<'r>> {
6350 PushOpPagePoolGetDumpRequest::new_without_header(self.request.buf)
6351 }
6352}
6353impl NetlinkRequest for RequestOpPagePoolGetDumpRequest<'_> {
6354 type ReplyType<'buf> = IterableOpPagePoolGetDumpReply<'buf>;
6355 fn protocol(&self) -> Protocol {
6356 Protocol::Generic("netdev".as_bytes())
6357 }
6358 fn flags(&self) -> u16 {
6359 self.request.flags
6360 }
6361 fn payload(&self) -> &[u8] {
6362 self.request.buf()
6363 }
6364 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
6365 OpPagePoolGetDumpReply::new(buf)
6366 }
6367 fn lookup(
6368 buf: &[u8],
6369 offset: usize,
6370 missing_type: Option<u16>,
6371 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6372 OpPagePoolGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
6373 }
6374}
6375#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6376pub struct PushOpPagePoolGetDoRequest<Prev: Rec> {
6377 pub(crate) prev: Option<Prev>,
6378 pub(crate) header_offset: Option<usize>,
6379}
6380impl<Prev: Rec> Rec for PushOpPagePoolGetDoRequest<Prev> {
6381 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6382 self.prev.as_mut().unwrap().as_rec_mut()
6383 }
6384}
6385impl<Prev: Rec> PushOpPagePoolGetDoRequest<Prev> {
6386 pub fn new(mut prev: Prev) -> Self {
6387 Self::write_header(&mut prev);
6388 Self::new_without_header(prev)
6389 }
6390 fn new_without_header(prev: Prev) -> Self {
6391 Self {
6392 prev: Some(prev),
6393 header_offset: None,
6394 }
6395 }
6396 fn write_header(prev: &mut Prev) {
6397 let mut header = PushBuiltinNfgenmsg::new();
6398 header.set_cmd(5u8);
6399 header.set_version(1u8);
6400 prev.as_rec_mut().extend(header.as_slice());
6401 }
6402 pub fn end_nested(mut self) -> Prev {
6403 let mut prev = self.prev.take().unwrap();
6404 if let Some(header_offset) = &self.header_offset {
6405 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6406 }
6407 prev
6408 }
6409 #[doc = "Unique ID of a Page Pool instance."]
6410 pub fn push_id(mut self, value: u32) -> Self {
6411 push_header(self.as_rec_mut(), 1u16, 4 as u16);
6412 self.as_rec_mut().extend(value.to_ne_bytes());
6413 self
6414 }
6415}
6416impl<Prev: Rec> Drop for PushOpPagePoolGetDoRequest<Prev> {
6417 fn drop(&mut self) {
6418 if let Some(prev) = &mut self.prev {
6419 if let Some(header_offset) = &self.header_offset {
6420 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6421 }
6422 }
6423 }
6424}
6425#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6426#[derive(Clone)]
6427pub enum OpPagePoolGetDoRequest {
6428 #[doc = "Unique ID of a Page Pool instance."]
6429 Id(u32),
6430}
6431impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6432 #[doc = "Unique ID of a Page Pool instance."]
6433 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6434 let mut iter = self.clone();
6435 iter.pos = 0;
6436 for attr in iter {
6437 if let OpPagePoolGetDoRequest::Id(val) = attr? {
6438 return Ok(val);
6439 }
6440 }
6441 Err(ErrorContext::new_missing(
6442 "OpPagePoolGetDoRequest",
6443 "Id",
6444 self.orig_loc,
6445 self.buf.as_ptr() as usize,
6446 ))
6447 }
6448}
6449impl OpPagePoolGetDoRequest {
6450 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoRequest<'a> {
6451 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6452 IterableOpPagePoolGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
6453 }
6454 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6455 PagePool::attr_from_type(r#type)
6456 }
6457}
6458#[derive(Clone, Copy, Default)]
6459pub struct IterableOpPagePoolGetDoRequest<'a> {
6460 buf: &'a [u8],
6461 pos: usize,
6462 orig_loc: usize,
6463}
6464impl<'a> IterableOpPagePoolGetDoRequest<'a> {
6465 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6466 Self {
6467 buf,
6468 pos: 0,
6469 orig_loc,
6470 }
6471 }
6472 pub fn get_buf(&self) -> &'a [u8] {
6473 self.buf
6474 }
6475}
6476impl<'a> Iterator for IterableOpPagePoolGetDoRequest<'a> {
6477 type Item = Result<OpPagePoolGetDoRequest, ErrorContext>;
6478 fn next(&mut self) -> Option<Self::Item> {
6479 if self.buf.len() == self.pos {
6480 return None;
6481 }
6482 let pos = self.pos;
6483 let mut r#type = None;
6484 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6485 r#type = Some(header.r#type);
6486 let res = match header.r#type {
6487 1u16 => OpPagePoolGetDoRequest::Id({
6488 let res = parse_u32(next);
6489 let Some(val) = res else { break };
6490 val
6491 }),
6492 n => {
6493 if cfg!(any(test, feature = "deny-unknown-attrs")) {
6494 break;
6495 } else {
6496 continue;
6497 }
6498 }
6499 };
6500 return Some(Ok(res));
6501 }
6502 Some(Err(ErrorContext::new(
6503 "OpPagePoolGetDoRequest",
6504 r#type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6505 self.orig_loc,
6506 self.buf.as_ptr().wrapping_add(pos) as usize,
6507 )))
6508 }
6509}
6510impl std::fmt::Debug for IterableOpPagePoolGetDoRequest<'_> {
6511 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6512 let mut fmt = f.debug_struct("OpPagePoolGetDoRequest");
6513 for attr in self.clone() {
6514 let attr = match attr {
6515 Ok(a) => a,
6516 Err(err) => {
6517 fmt.finish()?;
6518 f.write_str("Err(")?;
6519 err.fmt(f)?;
6520 return f.write_str(")");
6521 }
6522 };
6523 match attr {
6524 OpPagePoolGetDoRequest::Id(val) => fmt.field("Id", &val),
6525 };
6526 }
6527 fmt.finish()
6528 }
6529}
6530impl IterableOpPagePoolGetDoRequest<'_> {
6531 pub fn lookup_attr(
6532 &self,
6533 offset: usize,
6534 missing_type: Option<u16>,
6535 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6536 let mut stack = Vec::new();
6537 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6538 if cur == offset + PushBuiltinNfgenmsg::len() {
6539 stack.push(("OpPagePoolGetDoRequest", offset));
6540 return (
6541 stack,
6542 missing_type.and_then(|t| OpPagePoolGetDoRequest::attr_from_type(t)),
6543 );
6544 }
6545 if cur > offset || cur + self.buf.len() < offset {
6546 return (stack, None);
6547 }
6548 let mut attrs = self.clone();
6549 let mut last_off = cur + attrs.pos;
6550 while let Some(attr) = attrs.next() {
6551 let Ok(attr) = attr else { break };
6552 match attr {
6553 OpPagePoolGetDoRequest::Id(val) => {
6554 if last_off == offset {
6555 stack.push(("Id", last_off));
6556 break;
6557 }
6558 }
6559 _ => {}
6560 };
6561 last_off = cur + attrs.pos;
6562 }
6563 if !stack.is_empty() {
6564 stack.push(("OpPagePoolGetDoRequest", cur));
6565 }
6566 (stack, None)
6567 }
6568}
6569#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6570pub struct PushOpPagePoolGetDoReply<Prev: Rec> {
6571 pub(crate) prev: Option<Prev>,
6572 pub(crate) header_offset: Option<usize>,
6573}
6574impl<Prev: Rec> Rec for PushOpPagePoolGetDoReply<Prev> {
6575 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
6576 self.prev.as_mut().unwrap().as_rec_mut()
6577 }
6578}
6579impl<Prev: Rec> PushOpPagePoolGetDoReply<Prev> {
6580 pub fn new(mut prev: Prev) -> Self {
6581 Self::write_header(&mut prev);
6582 Self::new_without_header(prev)
6583 }
6584 fn new_without_header(prev: Prev) -> Self {
6585 Self {
6586 prev: Some(prev),
6587 header_offset: None,
6588 }
6589 }
6590 fn write_header(prev: &mut Prev) {
6591 let mut header = PushBuiltinNfgenmsg::new();
6592 header.set_cmd(5u8);
6593 header.set_version(1u8);
6594 prev.as_rec_mut().extend(header.as_slice());
6595 }
6596 pub fn end_nested(mut self) -> Prev {
6597 let mut prev = self.prev.take().unwrap();
6598 if let Some(header_offset) = &self.header_offset {
6599 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6600 }
6601 prev
6602 }
6603 #[doc = "Unique ID of a Page Pool instance."]
6604 pub fn push_id(mut self, value: u32) -> Self {
6605 push_header(self.as_rec_mut(), 1u16, 4 as u16);
6606 self.as_rec_mut().extend(value.to_ne_bytes());
6607 self
6608 }
6609 #[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"]
6610 pub fn push_ifindex(mut self, value: u32) -> Self {
6611 push_header(self.as_rec_mut(), 2u16, 4 as u16);
6612 self.as_rec_mut().extend(value.to_ne_bytes());
6613 self
6614 }
6615 #[doc = "Id of NAPI using this Page Pool instance."]
6616 pub fn push_napi_id(mut self, value: u32) -> Self {
6617 push_header(self.as_rec_mut(), 3u16, 4 as u16);
6618 self.as_rec_mut().extend(value.to_ne_bytes());
6619 self
6620 }
6621 #[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"]
6622 pub fn push_inflight(mut self, value: u32) -> Self {
6623 push_header(self.as_rec_mut(), 4u16, 4 as u16);
6624 self.as_rec_mut().extend(value.to_ne_bytes());
6625 self
6626 }
6627 #[doc = "Amount of memory held by inflight pages.\n"]
6628 pub fn push_inflight_mem(mut self, value: u32) -> Self {
6629 push_header(self.as_rec_mut(), 5u16, 4 as u16);
6630 self.as_rec_mut().extend(value.to_ne_bytes());
6631 self
6632 }
6633 #[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"]
6634 pub fn push_detach_time(mut self, value: u32) -> Self {
6635 push_header(self.as_rec_mut(), 6u16, 4 as u16);
6636 self.as_rec_mut().extend(value.to_ne_bytes());
6637 self
6638 }
6639 #[doc = "ID of the dmabuf this page-pool is attached to."]
6640 pub fn push_dmabuf(mut self, value: u32) -> Self {
6641 push_header(self.as_rec_mut(), 7u16, 4 as u16);
6642 self.as_rec_mut().extend(value.to_ne_bytes());
6643 self
6644 }
6645 #[doc = "io-uring memory provider information."]
6646 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
6647 let header_offset = push_nested_header(self.as_rec_mut(), 8u16);
6648 PushIoUringProviderInfo {
6649 prev: Some(self),
6650 header_offset: Some(header_offset),
6651 }
6652 }
6653}
6654impl<Prev: Rec> Drop for PushOpPagePoolGetDoReply<Prev> {
6655 fn drop(&mut self) {
6656 if let Some(prev) = &mut self.prev {
6657 if let Some(header_offset) = &self.header_offset {
6658 finalize_nested_header(prev.as_rec_mut(), *header_offset);
6659 }
6660 }
6661 }
6662}
6663#[doc = "Get / dump information about Page Pools.\n(Only Page Pools associated with a net_device can be listed.)\n"]
6664#[derive(Clone)]
6665pub enum OpPagePoolGetDoReply<'a> {
6666 #[doc = "Unique ID of a Page Pool instance."]
6667 Id(u32),
6668 #[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"]
6669 Ifindex(u32),
6670 #[doc = "Id of NAPI using this Page Pool instance."]
6671 NapiId(u32),
6672 #[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"]
6673 Inflight(u32),
6674 #[doc = "Amount of memory held by inflight pages.\n"]
6675 InflightMem(u32),
6676 #[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"]
6677 DetachTime(u32),
6678 #[doc = "ID of the dmabuf this page-pool is attached to."]
6679 Dmabuf(u32),
6680 #[doc = "io-uring memory provider information."]
6681 IoUring(IterableIoUringProviderInfo<'a>),
6682}
6683impl<'a> IterableOpPagePoolGetDoReply<'a> {
6684 #[doc = "Unique ID of a Page Pool instance."]
6685 pub fn get_id(&self) -> Result<u32, ErrorContext> {
6686 let mut iter = self.clone();
6687 iter.pos = 0;
6688 for attr in iter {
6689 if let OpPagePoolGetDoReply::Id(val) = attr? {
6690 return Ok(val);
6691 }
6692 }
6693 Err(ErrorContext::new_missing(
6694 "OpPagePoolGetDoReply",
6695 "Id",
6696 self.orig_loc,
6697 self.buf.as_ptr() as usize,
6698 ))
6699 }
6700 #[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"]
6701 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
6702 let mut iter = self.clone();
6703 iter.pos = 0;
6704 for attr in iter {
6705 if let OpPagePoolGetDoReply::Ifindex(val) = attr? {
6706 return Ok(val);
6707 }
6708 }
6709 Err(ErrorContext::new_missing(
6710 "OpPagePoolGetDoReply",
6711 "Ifindex",
6712 self.orig_loc,
6713 self.buf.as_ptr() as usize,
6714 ))
6715 }
6716 #[doc = "Id of NAPI using this Page Pool instance."]
6717 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
6718 let mut iter = self.clone();
6719 iter.pos = 0;
6720 for attr in iter {
6721 if let OpPagePoolGetDoReply::NapiId(val) = attr? {
6722 return Ok(val);
6723 }
6724 }
6725 Err(ErrorContext::new_missing(
6726 "OpPagePoolGetDoReply",
6727 "NapiId",
6728 self.orig_loc,
6729 self.buf.as_ptr() as usize,
6730 ))
6731 }
6732 #[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"]
6733 pub fn get_inflight(&self) -> Result<u32, ErrorContext> {
6734 let mut iter = self.clone();
6735 iter.pos = 0;
6736 for attr in iter {
6737 if let OpPagePoolGetDoReply::Inflight(val) = attr? {
6738 return Ok(val);
6739 }
6740 }
6741 Err(ErrorContext::new_missing(
6742 "OpPagePoolGetDoReply",
6743 "Inflight",
6744 self.orig_loc,
6745 self.buf.as_ptr() as usize,
6746 ))
6747 }
6748 #[doc = "Amount of memory held by inflight pages.\n"]
6749 pub fn get_inflight_mem(&self) -> Result<u32, ErrorContext> {
6750 let mut iter = self.clone();
6751 iter.pos = 0;
6752 for attr in iter {
6753 if let OpPagePoolGetDoReply::InflightMem(val) = attr? {
6754 return Ok(val);
6755 }
6756 }
6757 Err(ErrorContext::new_missing(
6758 "OpPagePoolGetDoReply",
6759 "InflightMem",
6760 self.orig_loc,
6761 self.buf.as_ptr() as usize,
6762 ))
6763 }
6764 #[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"]
6765 pub fn get_detach_time(&self) -> Result<u32, ErrorContext> {
6766 let mut iter = self.clone();
6767 iter.pos = 0;
6768 for attr in iter {
6769 if let OpPagePoolGetDoReply::DetachTime(val) = attr? {
6770 return Ok(val);
6771 }
6772 }
6773 Err(ErrorContext::new_missing(
6774 "OpPagePoolGetDoReply",
6775 "DetachTime",
6776 self.orig_loc,
6777 self.buf.as_ptr() as usize,
6778 ))
6779 }
6780 #[doc = "ID of the dmabuf this page-pool is attached to."]
6781 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
6782 let mut iter = self.clone();
6783 iter.pos = 0;
6784 for attr in iter {
6785 if let OpPagePoolGetDoReply::Dmabuf(val) = attr? {
6786 return Ok(val);
6787 }
6788 }
6789 Err(ErrorContext::new_missing(
6790 "OpPagePoolGetDoReply",
6791 "Dmabuf",
6792 self.orig_loc,
6793 self.buf.as_ptr() as usize,
6794 ))
6795 }
6796 #[doc = "io-uring memory provider information."]
6797 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
6798 let mut iter = self.clone();
6799 iter.pos = 0;
6800 for attr in iter {
6801 if let OpPagePoolGetDoReply::IoUring(val) = attr? {
6802 return Ok(val);
6803 }
6804 }
6805 Err(ErrorContext::new_missing(
6806 "OpPagePoolGetDoReply",
6807 "IoUring",
6808 self.orig_loc,
6809 self.buf.as_ptr() as usize,
6810 ))
6811 }
6812}
6813impl OpPagePoolGetDoReply<'_> {
6814 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolGetDoReply<'a> {
6815 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
6816 IterableOpPagePoolGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
6817 }
6818 fn attr_from_type(r#type: u16) -> Option<&'static str> {
6819 PagePool::attr_from_type(r#type)
6820 }
6821}
6822#[derive(Clone, Copy, Default)]
6823pub struct IterableOpPagePoolGetDoReply<'a> {
6824 buf: &'a [u8],
6825 pos: usize,
6826 orig_loc: usize,
6827}
6828impl<'a> IterableOpPagePoolGetDoReply<'a> {
6829 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
6830 Self {
6831 buf,
6832 pos: 0,
6833 orig_loc,
6834 }
6835 }
6836 pub fn get_buf(&self) -> &'a [u8] {
6837 self.buf
6838 }
6839}
6840impl<'a> Iterator for IterableOpPagePoolGetDoReply<'a> {
6841 type Item = Result<OpPagePoolGetDoReply<'a>, ErrorContext>;
6842 fn next(&mut self) -> Option<Self::Item> {
6843 if self.buf.len() == self.pos {
6844 return None;
6845 }
6846 let pos = self.pos;
6847 let mut r#type = None;
6848 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
6849 r#type = Some(header.r#type);
6850 let res = match header.r#type {
6851 1u16 => OpPagePoolGetDoReply::Id({
6852 let res = parse_u32(next);
6853 let Some(val) = res else { break };
6854 val
6855 }),
6856 2u16 => OpPagePoolGetDoReply::Ifindex({
6857 let res = parse_u32(next);
6858 let Some(val) = res else { break };
6859 val
6860 }),
6861 3u16 => OpPagePoolGetDoReply::NapiId({
6862 let res = parse_u32(next);
6863 let Some(val) = res else { break };
6864 val
6865 }),
6866 4u16 => OpPagePoolGetDoReply::Inflight({
6867 let res = parse_u32(next);
6868 let Some(val) = res else { break };
6869 val
6870 }),
6871 5u16 => OpPagePoolGetDoReply::InflightMem({
6872 let res = parse_u32(next);
6873 let Some(val) = res else { break };
6874 val
6875 }),
6876 6u16 => OpPagePoolGetDoReply::DetachTime({
6877 let res = parse_u32(next);
6878 let Some(val) = res else { break };
6879 val
6880 }),
6881 7u16 => OpPagePoolGetDoReply::Dmabuf({
6882 let res = parse_u32(next);
6883 let Some(val) = res else { break };
6884 val
6885 }),
6886 8u16 => OpPagePoolGetDoReply::IoUring({
6887 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
6888 let Some(val) = res else { break };
6889 val
6890 }),
6891 n => {
6892 if cfg!(any(test, feature = "deny-unknown-attrs")) {
6893 break;
6894 } else {
6895 continue;
6896 }
6897 }
6898 };
6899 return Some(Ok(res));
6900 }
6901 Some(Err(ErrorContext::new(
6902 "OpPagePoolGetDoReply",
6903 r#type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6904 self.orig_loc,
6905 self.buf.as_ptr().wrapping_add(pos) as usize,
6906 )))
6907 }
6908}
6909impl<'a> std::fmt::Debug for IterableOpPagePoolGetDoReply<'_> {
6910 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6911 let mut fmt = f.debug_struct("OpPagePoolGetDoReply");
6912 for attr in self.clone() {
6913 let attr = match attr {
6914 Ok(a) => a,
6915 Err(err) => {
6916 fmt.finish()?;
6917 f.write_str("Err(")?;
6918 err.fmt(f)?;
6919 return f.write_str(")");
6920 }
6921 };
6922 match attr {
6923 OpPagePoolGetDoReply::Id(val) => fmt.field("Id", &val),
6924 OpPagePoolGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
6925 OpPagePoolGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
6926 OpPagePoolGetDoReply::Inflight(val) => fmt.field("Inflight", &val),
6927 OpPagePoolGetDoReply::InflightMem(val) => fmt.field("InflightMem", &val),
6928 OpPagePoolGetDoReply::DetachTime(val) => fmt.field("DetachTime", &val),
6929 OpPagePoolGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
6930 OpPagePoolGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
6931 };
6932 }
6933 fmt.finish()
6934 }
6935}
6936impl IterableOpPagePoolGetDoReply<'_> {
6937 pub fn lookup_attr(
6938 &self,
6939 offset: usize,
6940 missing_type: Option<u16>,
6941 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
6942 let mut stack = Vec::new();
6943 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
6944 if cur == offset + PushBuiltinNfgenmsg::len() {
6945 stack.push(("OpPagePoolGetDoReply", offset));
6946 return (
6947 stack,
6948 missing_type.and_then(|t| OpPagePoolGetDoReply::attr_from_type(t)),
6949 );
6950 }
6951 if cur > offset || cur + self.buf.len() < offset {
6952 return (stack, None);
6953 }
6954 let mut attrs = self.clone();
6955 let mut last_off = cur + attrs.pos;
6956 let mut missing = None;
6957 while let Some(attr) = attrs.next() {
6958 let Ok(attr) = attr else { break };
6959 match attr {
6960 OpPagePoolGetDoReply::Id(val) => {
6961 if last_off == offset {
6962 stack.push(("Id", last_off));
6963 break;
6964 }
6965 }
6966 OpPagePoolGetDoReply::Ifindex(val) => {
6967 if last_off == offset {
6968 stack.push(("Ifindex", last_off));
6969 break;
6970 }
6971 }
6972 OpPagePoolGetDoReply::NapiId(val) => {
6973 if last_off == offset {
6974 stack.push(("NapiId", last_off));
6975 break;
6976 }
6977 }
6978 OpPagePoolGetDoReply::Inflight(val) => {
6979 if last_off == offset {
6980 stack.push(("Inflight", last_off));
6981 break;
6982 }
6983 }
6984 OpPagePoolGetDoReply::InflightMem(val) => {
6985 if last_off == offset {
6986 stack.push(("InflightMem", last_off));
6987 break;
6988 }
6989 }
6990 OpPagePoolGetDoReply::DetachTime(val) => {
6991 if last_off == offset {
6992 stack.push(("DetachTime", last_off));
6993 break;
6994 }
6995 }
6996 OpPagePoolGetDoReply::Dmabuf(val) => {
6997 if last_off == offset {
6998 stack.push(("Dmabuf", last_off));
6999 break;
7000 }
7001 }
7002 OpPagePoolGetDoReply::IoUring(val) => {
7003 (stack, missing) = val.lookup_attr(offset, missing_type);
7004 if !stack.is_empty() {
7005 break;
7006 }
7007 }
7008 _ => {}
7009 };
7010 last_off = cur + attrs.pos;
7011 }
7012 if !stack.is_empty() {
7013 stack.push(("OpPagePoolGetDoReply", cur));
7014 }
7015 (stack, missing)
7016 }
7017}
7018#[derive(Debug)]
7019pub struct RequestOpPagePoolGetDoRequest<'r> {
7020 request: Request<'r>,
7021}
7022impl<'r> RequestOpPagePoolGetDoRequest<'r> {
7023 pub fn new(mut request: Request<'r>) -> Self {
7024 PushOpPagePoolGetDoRequest::write_header(&mut request.buf_mut());
7025 Self { request: request }
7026 }
7027 pub fn encode(&mut self) -> PushOpPagePoolGetDoRequest<&mut Vec<u8>> {
7028 PushOpPagePoolGetDoRequest::new_without_header(self.request.buf_mut())
7029 }
7030 pub fn into_encoder(self) -> PushOpPagePoolGetDoRequest<RequestBuf<'r>> {
7031 PushOpPagePoolGetDoRequest::new_without_header(self.request.buf)
7032 }
7033}
7034impl NetlinkRequest for RequestOpPagePoolGetDoRequest<'_> {
7035 type ReplyType<'buf> = IterableOpPagePoolGetDoReply<'buf>;
7036 fn protocol(&self) -> Protocol {
7037 Protocol::Generic("netdev".as_bytes())
7038 }
7039 fn flags(&self) -> u16 {
7040 self.request.flags
7041 }
7042 fn payload(&self) -> &[u8] {
7043 self.request.buf()
7044 }
7045 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7046 OpPagePoolGetDoReply::new(buf)
7047 }
7048 fn lookup(
7049 buf: &[u8],
7050 offset: usize,
7051 missing_type: Option<u16>,
7052 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7053 OpPagePoolGetDoRequest::new(buf).lookup_attr(offset, missing_type)
7054 }
7055}
7056#[doc = "Get page pool statistics."]
7057pub struct PushOpPagePoolStatsGetDumpRequest<Prev: Rec> {
7058 pub(crate) prev: Option<Prev>,
7059 pub(crate) header_offset: Option<usize>,
7060}
7061impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpRequest<Prev> {
7062 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7063 self.prev.as_mut().unwrap().as_rec_mut()
7064 }
7065}
7066impl<Prev: Rec> PushOpPagePoolStatsGetDumpRequest<Prev> {
7067 pub fn new(mut prev: Prev) -> Self {
7068 Self::write_header(&mut prev);
7069 Self::new_without_header(prev)
7070 }
7071 fn new_without_header(prev: Prev) -> Self {
7072 Self {
7073 prev: Some(prev),
7074 header_offset: None,
7075 }
7076 }
7077 fn write_header(prev: &mut Prev) {
7078 let mut header = PushBuiltinNfgenmsg::new();
7079 header.set_cmd(9u8);
7080 header.set_version(1u8);
7081 prev.as_rec_mut().extend(header.as_slice());
7082 }
7083 pub fn end_nested(mut self) -> Prev {
7084 let mut prev = self.prev.take().unwrap();
7085 if let Some(header_offset) = &self.header_offset {
7086 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7087 }
7088 prev
7089 }
7090}
7091impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpRequest<Prev> {
7092 fn drop(&mut self) {
7093 if let Some(prev) = &mut self.prev {
7094 if let Some(header_offset) = &self.header_offset {
7095 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7096 }
7097 }
7098 }
7099}
7100#[doc = "Get page pool statistics."]
7101#[derive(Clone)]
7102pub enum OpPagePoolStatsGetDumpRequest {}
7103impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {}
7104impl OpPagePoolStatsGetDumpRequest {
7105 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpRequest<'a> {
7106 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7107 IterableOpPagePoolStatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
7108 }
7109 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7110 PagePoolStats::attr_from_type(r#type)
7111 }
7112}
7113#[derive(Clone, Copy, Default)]
7114pub struct IterableOpPagePoolStatsGetDumpRequest<'a> {
7115 buf: &'a [u8],
7116 pos: usize,
7117 orig_loc: usize,
7118}
7119impl<'a> IterableOpPagePoolStatsGetDumpRequest<'a> {
7120 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7121 Self {
7122 buf,
7123 pos: 0,
7124 orig_loc,
7125 }
7126 }
7127 pub fn get_buf(&self) -> &'a [u8] {
7128 self.buf
7129 }
7130}
7131impl<'a> Iterator for IterableOpPagePoolStatsGetDumpRequest<'a> {
7132 type Item = Result<OpPagePoolStatsGetDumpRequest, ErrorContext>;
7133 fn next(&mut self) -> Option<Self::Item> {
7134 if self.buf.len() == self.pos {
7135 return None;
7136 }
7137 let pos = self.pos;
7138 let mut r#type = None;
7139 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7140 r#type = Some(header.r#type);
7141 let res = match header.r#type {
7142 n => {
7143 if cfg!(any(test, feature = "deny-unknown-attrs")) {
7144 break;
7145 } else {
7146 continue;
7147 }
7148 }
7149 };
7150 return Some(Ok(res));
7151 }
7152 Some(Err(ErrorContext::new(
7153 "OpPagePoolStatsGetDumpRequest",
7154 r#type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7155 self.orig_loc,
7156 self.buf.as_ptr().wrapping_add(pos) as usize,
7157 )))
7158 }
7159}
7160impl std::fmt::Debug for IterableOpPagePoolStatsGetDumpRequest<'_> {
7161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7162 let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpRequest");
7163 for attr in self.clone() {
7164 let attr = match attr {
7165 Ok(a) => a,
7166 Err(err) => {
7167 fmt.finish()?;
7168 f.write_str("Err(")?;
7169 err.fmt(f)?;
7170 return f.write_str(")");
7171 }
7172 };
7173 match attr {};
7174 }
7175 fmt.finish()
7176 }
7177}
7178impl IterableOpPagePoolStatsGetDumpRequest<'_> {
7179 pub fn lookup_attr(
7180 &self,
7181 offset: usize,
7182 missing_type: Option<u16>,
7183 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7184 let mut stack = Vec::new();
7185 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7186 if cur == offset + PushBuiltinNfgenmsg::len() {
7187 stack.push(("OpPagePoolStatsGetDumpRequest", offset));
7188 return (
7189 stack,
7190 missing_type.and_then(|t| OpPagePoolStatsGetDumpRequest::attr_from_type(t)),
7191 );
7192 }
7193 (stack, None)
7194 }
7195}
7196#[doc = "Get page pool statistics."]
7197pub struct PushOpPagePoolStatsGetDumpReply<Prev: Rec> {
7198 pub(crate) prev: Option<Prev>,
7199 pub(crate) header_offset: Option<usize>,
7200}
7201impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDumpReply<Prev> {
7202 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7203 self.prev.as_mut().unwrap().as_rec_mut()
7204 }
7205}
7206impl<Prev: Rec> PushOpPagePoolStatsGetDumpReply<Prev> {
7207 pub fn new(mut prev: Prev) -> Self {
7208 Self::write_header(&mut prev);
7209 Self::new_without_header(prev)
7210 }
7211 fn new_without_header(prev: Prev) -> Self {
7212 Self {
7213 prev: Some(prev),
7214 header_offset: None,
7215 }
7216 }
7217 fn write_header(prev: &mut Prev) {
7218 let mut header = PushBuiltinNfgenmsg::new();
7219 header.set_cmd(9u8);
7220 header.set_version(1u8);
7221 prev.as_rec_mut().extend(header.as_slice());
7222 }
7223 pub fn end_nested(mut self) -> Prev {
7224 let mut prev = self.prev.take().unwrap();
7225 if let Some(header_offset) = &self.header_offset {
7226 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7227 }
7228 prev
7229 }
7230 #[doc = "Page pool identifying information."]
7231 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7232 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7233 PushPagePoolInfo {
7234 prev: Some(self),
7235 header_offset: Some(header_offset),
7236 }
7237 }
7238 pub fn push_alloc_fast(mut self, value: u32) -> Self {
7239 push_header(self.as_rec_mut(), 8u16, 4 as u16);
7240 self.as_rec_mut().extend(value.to_ne_bytes());
7241 self
7242 }
7243 pub fn push_alloc_slow(mut self, value: u32) -> Self {
7244 push_header(self.as_rec_mut(), 9u16, 4 as u16);
7245 self.as_rec_mut().extend(value.to_ne_bytes());
7246 self
7247 }
7248 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
7249 push_header(self.as_rec_mut(), 10u16, 4 as u16);
7250 self.as_rec_mut().extend(value.to_ne_bytes());
7251 self
7252 }
7253 pub fn push_alloc_empty(mut self, value: u32) -> Self {
7254 push_header(self.as_rec_mut(), 11u16, 4 as u16);
7255 self.as_rec_mut().extend(value.to_ne_bytes());
7256 self
7257 }
7258 pub fn push_alloc_refill(mut self, value: u32) -> Self {
7259 push_header(self.as_rec_mut(), 12u16, 4 as u16);
7260 self.as_rec_mut().extend(value.to_ne_bytes());
7261 self
7262 }
7263 pub fn push_alloc_waive(mut self, value: u32) -> Self {
7264 push_header(self.as_rec_mut(), 13u16, 4 as u16);
7265 self.as_rec_mut().extend(value.to_ne_bytes());
7266 self
7267 }
7268 pub fn push_recycle_cached(mut self, value: u32) -> Self {
7269 push_header(self.as_rec_mut(), 14u16, 4 as u16);
7270 self.as_rec_mut().extend(value.to_ne_bytes());
7271 self
7272 }
7273 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
7274 push_header(self.as_rec_mut(), 15u16, 4 as u16);
7275 self.as_rec_mut().extend(value.to_ne_bytes());
7276 self
7277 }
7278 pub fn push_recycle_ring(mut self, value: u32) -> Self {
7279 push_header(self.as_rec_mut(), 16u16, 4 as u16);
7280 self.as_rec_mut().extend(value.to_ne_bytes());
7281 self
7282 }
7283 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
7284 push_header(self.as_rec_mut(), 17u16, 4 as u16);
7285 self.as_rec_mut().extend(value.to_ne_bytes());
7286 self
7287 }
7288 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
7289 push_header(self.as_rec_mut(), 18u16, 4 as u16);
7290 self.as_rec_mut().extend(value.to_ne_bytes());
7291 self
7292 }
7293}
7294impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDumpReply<Prev> {
7295 fn drop(&mut self) {
7296 if let Some(prev) = &mut self.prev {
7297 if let Some(header_offset) = &self.header_offset {
7298 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7299 }
7300 }
7301 }
7302}
7303#[doc = "Get page pool statistics."]
7304#[derive(Clone)]
7305pub enum OpPagePoolStatsGetDumpReply<'a> {
7306 #[doc = "Page pool identifying information."]
7307 Info(IterablePagePoolInfo<'a>),
7308 AllocFast(u32),
7309 AllocSlow(u32),
7310 AllocSlowHighOrder(u32),
7311 AllocEmpty(u32),
7312 AllocRefill(u32),
7313 AllocWaive(u32),
7314 RecycleCached(u32),
7315 RecycleCacheFull(u32),
7316 RecycleRing(u32),
7317 RecycleRingFull(u32),
7318 RecycleReleasedRefcnt(u32),
7319}
7320impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7321 #[doc = "Page pool identifying information."]
7322 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7323 let mut iter = self.clone();
7324 iter.pos = 0;
7325 for attr in iter {
7326 if let OpPagePoolStatsGetDumpReply::Info(val) = attr? {
7327 return Ok(val);
7328 }
7329 }
7330 Err(ErrorContext::new_missing(
7331 "OpPagePoolStatsGetDumpReply",
7332 "Info",
7333 self.orig_loc,
7334 self.buf.as_ptr() as usize,
7335 ))
7336 }
7337 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
7338 let mut iter = self.clone();
7339 iter.pos = 0;
7340 for attr in iter {
7341 if let OpPagePoolStatsGetDumpReply::AllocFast(val) = attr? {
7342 return Ok(val);
7343 }
7344 }
7345 Err(ErrorContext::new_missing(
7346 "OpPagePoolStatsGetDumpReply",
7347 "AllocFast",
7348 self.orig_loc,
7349 self.buf.as_ptr() as usize,
7350 ))
7351 }
7352 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
7353 let mut iter = self.clone();
7354 iter.pos = 0;
7355 for attr in iter {
7356 if let OpPagePoolStatsGetDumpReply::AllocSlow(val) = attr? {
7357 return Ok(val);
7358 }
7359 }
7360 Err(ErrorContext::new_missing(
7361 "OpPagePoolStatsGetDumpReply",
7362 "AllocSlow",
7363 self.orig_loc,
7364 self.buf.as_ptr() as usize,
7365 ))
7366 }
7367 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
7368 let mut iter = self.clone();
7369 iter.pos = 0;
7370 for attr in iter {
7371 if let OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) = attr? {
7372 return Ok(val);
7373 }
7374 }
7375 Err(ErrorContext::new_missing(
7376 "OpPagePoolStatsGetDumpReply",
7377 "AllocSlowHighOrder",
7378 self.orig_loc,
7379 self.buf.as_ptr() as usize,
7380 ))
7381 }
7382 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
7383 let mut iter = self.clone();
7384 iter.pos = 0;
7385 for attr in iter {
7386 if let OpPagePoolStatsGetDumpReply::AllocEmpty(val) = attr? {
7387 return Ok(val);
7388 }
7389 }
7390 Err(ErrorContext::new_missing(
7391 "OpPagePoolStatsGetDumpReply",
7392 "AllocEmpty",
7393 self.orig_loc,
7394 self.buf.as_ptr() as usize,
7395 ))
7396 }
7397 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
7398 let mut iter = self.clone();
7399 iter.pos = 0;
7400 for attr in iter {
7401 if let OpPagePoolStatsGetDumpReply::AllocRefill(val) = attr? {
7402 return Ok(val);
7403 }
7404 }
7405 Err(ErrorContext::new_missing(
7406 "OpPagePoolStatsGetDumpReply",
7407 "AllocRefill",
7408 self.orig_loc,
7409 self.buf.as_ptr() as usize,
7410 ))
7411 }
7412 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
7413 let mut iter = self.clone();
7414 iter.pos = 0;
7415 for attr in iter {
7416 if let OpPagePoolStatsGetDumpReply::AllocWaive(val) = attr? {
7417 return Ok(val);
7418 }
7419 }
7420 Err(ErrorContext::new_missing(
7421 "OpPagePoolStatsGetDumpReply",
7422 "AllocWaive",
7423 self.orig_loc,
7424 self.buf.as_ptr() as usize,
7425 ))
7426 }
7427 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
7428 let mut iter = self.clone();
7429 iter.pos = 0;
7430 for attr in iter {
7431 if let OpPagePoolStatsGetDumpReply::RecycleCached(val) = attr? {
7432 return Ok(val);
7433 }
7434 }
7435 Err(ErrorContext::new_missing(
7436 "OpPagePoolStatsGetDumpReply",
7437 "RecycleCached",
7438 self.orig_loc,
7439 self.buf.as_ptr() as usize,
7440 ))
7441 }
7442 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
7443 let mut iter = self.clone();
7444 iter.pos = 0;
7445 for attr in iter {
7446 if let OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) = attr? {
7447 return Ok(val);
7448 }
7449 }
7450 Err(ErrorContext::new_missing(
7451 "OpPagePoolStatsGetDumpReply",
7452 "RecycleCacheFull",
7453 self.orig_loc,
7454 self.buf.as_ptr() as usize,
7455 ))
7456 }
7457 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
7458 let mut iter = self.clone();
7459 iter.pos = 0;
7460 for attr in iter {
7461 if let OpPagePoolStatsGetDumpReply::RecycleRing(val) = attr? {
7462 return Ok(val);
7463 }
7464 }
7465 Err(ErrorContext::new_missing(
7466 "OpPagePoolStatsGetDumpReply",
7467 "RecycleRing",
7468 self.orig_loc,
7469 self.buf.as_ptr() as usize,
7470 ))
7471 }
7472 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
7473 let mut iter = self.clone();
7474 iter.pos = 0;
7475 for attr in iter {
7476 if let OpPagePoolStatsGetDumpReply::RecycleRingFull(val) = attr? {
7477 return Ok(val);
7478 }
7479 }
7480 Err(ErrorContext::new_missing(
7481 "OpPagePoolStatsGetDumpReply",
7482 "RecycleRingFull",
7483 self.orig_loc,
7484 self.buf.as_ptr() as usize,
7485 ))
7486 }
7487 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
7488 let mut iter = self.clone();
7489 iter.pos = 0;
7490 for attr in iter {
7491 if let OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) = attr? {
7492 return Ok(val);
7493 }
7494 }
7495 Err(ErrorContext::new_missing(
7496 "OpPagePoolStatsGetDumpReply",
7497 "RecycleReleasedRefcnt",
7498 self.orig_loc,
7499 self.buf.as_ptr() as usize,
7500 ))
7501 }
7502}
7503impl OpPagePoolStatsGetDumpReply<'_> {
7504 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDumpReply<'a> {
7505 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7506 IterableOpPagePoolStatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
7507 }
7508 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7509 PagePoolStats::attr_from_type(r#type)
7510 }
7511}
7512#[derive(Clone, Copy, Default)]
7513pub struct IterableOpPagePoolStatsGetDumpReply<'a> {
7514 buf: &'a [u8],
7515 pos: usize,
7516 orig_loc: usize,
7517}
7518impl<'a> IterableOpPagePoolStatsGetDumpReply<'a> {
7519 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7520 Self {
7521 buf,
7522 pos: 0,
7523 orig_loc,
7524 }
7525 }
7526 pub fn get_buf(&self) -> &'a [u8] {
7527 self.buf
7528 }
7529}
7530impl<'a> Iterator for IterableOpPagePoolStatsGetDumpReply<'a> {
7531 type Item = Result<OpPagePoolStatsGetDumpReply<'a>, ErrorContext>;
7532 fn next(&mut self) -> Option<Self::Item> {
7533 if self.buf.len() == self.pos {
7534 return None;
7535 }
7536 let pos = self.pos;
7537 let mut r#type = None;
7538 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7539 r#type = Some(header.r#type);
7540 let res = match header.r#type {
7541 1u16 => OpPagePoolStatsGetDumpReply::Info({
7542 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7543 let Some(val) = res else { break };
7544 val
7545 }),
7546 8u16 => OpPagePoolStatsGetDumpReply::AllocFast({
7547 let res = parse_u32(next);
7548 let Some(val) = res else { break };
7549 val
7550 }),
7551 9u16 => OpPagePoolStatsGetDumpReply::AllocSlow({
7552 let res = parse_u32(next);
7553 let Some(val) = res else { break };
7554 val
7555 }),
7556 10u16 => OpPagePoolStatsGetDumpReply::AllocSlowHighOrder({
7557 let res = parse_u32(next);
7558 let Some(val) = res else { break };
7559 val
7560 }),
7561 11u16 => OpPagePoolStatsGetDumpReply::AllocEmpty({
7562 let res = parse_u32(next);
7563 let Some(val) = res else { break };
7564 val
7565 }),
7566 12u16 => OpPagePoolStatsGetDumpReply::AllocRefill({
7567 let res = parse_u32(next);
7568 let Some(val) = res else { break };
7569 val
7570 }),
7571 13u16 => OpPagePoolStatsGetDumpReply::AllocWaive({
7572 let res = parse_u32(next);
7573 let Some(val) = res else { break };
7574 val
7575 }),
7576 14u16 => OpPagePoolStatsGetDumpReply::RecycleCached({
7577 let res = parse_u32(next);
7578 let Some(val) = res else { break };
7579 val
7580 }),
7581 15u16 => OpPagePoolStatsGetDumpReply::RecycleCacheFull({
7582 let res = parse_u32(next);
7583 let Some(val) = res else { break };
7584 val
7585 }),
7586 16u16 => OpPagePoolStatsGetDumpReply::RecycleRing({
7587 let res = parse_u32(next);
7588 let Some(val) = res else { break };
7589 val
7590 }),
7591 17u16 => OpPagePoolStatsGetDumpReply::RecycleRingFull({
7592 let res = parse_u32(next);
7593 let Some(val) = res else { break };
7594 val
7595 }),
7596 18u16 => OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt({
7597 let res = parse_u32(next);
7598 let Some(val) = res else { break };
7599 val
7600 }),
7601 n => {
7602 if cfg!(any(test, feature = "deny-unknown-attrs")) {
7603 break;
7604 } else {
7605 continue;
7606 }
7607 }
7608 };
7609 return Some(Ok(res));
7610 }
7611 Some(Err(ErrorContext::new(
7612 "OpPagePoolStatsGetDumpReply",
7613 r#type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7614 self.orig_loc,
7615 self.buf.as_ptr().wrapping_add(pos) as usize,
7616 )))
7617 }
7618}
7619impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDumpReply<'_> {
7620 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7621 let mut fmt = f.debug_struct("OpPagePoolStatsGetDumpReply");
7622 for attr in self.clone() {
7623 let attr = match attr {
7624 Ok(a) => a,
7625 Err(err) => {
7626 fmt.finish()?;
7627 f.write_str("Err(")?;
7628 err.fmt(f)?;
7629 return f.write_str(")");
7630 }
7631 };
7632 match attr {
7633 OpPagePoolStatsGetDumpReply::Info(val) => fmt.field("Info", &val),
7634 OpPagePoolStatsGetDumpReply::AllocFast(val) => fmt.field("AllocFast", &val),
7635 OpPagePoolStatsGetDumpReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
7636 OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7637 fmt.field("AllocSlowHighOrder", &val)
7638 }
7639 OpPagePoolStatsGetDumpReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
7640 OpPagePoolStatsGetDumpReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
7641 OpPagePoolStatsGetDumpReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
7642 OpPagePoolStatsGetDumpReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
7643 OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7644 fmt.field("RecycleCacheFull", &val)
7645 }
7646 OpPagePoolStatsGetDumpReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
7647 OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7648 fmt.field("RecycleRingFull", &val)
7649 }
7650 OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7651 fmt.field("RecycleReleasedRefcnt", &val)
7652 }
7653 };
7654 }
7655 fmt.finish()
7656 }
7657}
7658impl IterableOpPagePoolStatsGetDumpReply<'_> {
7659 pub fn lookup_attr(
7660 &self,
7661 offset: usize,
7662 missing_type: Option<u16>,
7663 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7664 let mut stack = Vec::new();
7665 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7666 if cur == offset + PushBuiltinNfgenmsg::len() {
7667 stack.push(("OpPagePoolStatsGetDumpReply", offset));
7668 return (
7669 stack,
7670 missing_type.and_then(|t| OpPagePoolStatsGetDumpReply::attr_from_type(t)),
7671 );
7672 }
7673 if cur > offset || cur + self.buf.len() < offset {
7674 return (stack, None);
7675 }
7676 let mut attrs = self.clone();
7677 let mut last_off = cur + attrs.pos;
7678 let mut missing = None;
7679 while let Some(attr) = attrs.next() {
7680 let Ok(attr) = attr else { break };
7681 match attr {
7682 OpPagePoolStatsGetDumpReply::Info(val) => {
7683 (stack, missing) = val.lookup_attr(offset, missing_type);
7684 if !stack.is_empty() {
7685 break;
7686 }
7687 }
7688 OpPagePoolStatsGetDumpReply::AllocFast(val) => {
7689 if last_off == offset {
7690 stack.push(("AllocFast", last_off));
7691 break;
7692 }
7693 }
7694 OpPagePoolStatsGetDumpReply::AllocSlow(val) => {
7695 if last_off == offset {
7696 stack.push(("AllocSlow", last_off));
7697 break;
7698 }
7699 }
7700 OpPagePoolStatsGetDumpReply::AllocSlowHighOrder(val) => {
7701 if last_off == offset {
7702 stack.push(("AllocSlowHighOrder", last_off));
7703 break;
7704 }
7705 }
7706 OpPagePoolStatsGetDumpReply::AllocEmpty(val) => {
7707 if last_off == offset {
7708 stack.push(("AllocEmpty", last_off));
7709 break;
7710 }
7711 }
7712 OpPagePoolStatsGetDumpReply::AllocRefill(val) => {
7713 if last_off == offset {
7714 stack.push(("AllocRefill", last_off));
7715 break;
7716 }
7717 }
7718 OpPagePoolStatsGetDumpReply::AllocWaive(val) => {
7719 if last_off == offset {
7720 stack.push(("AllocWaive", last_off));
7721 break;
7722 }
7723 }
7724 OpPagePoolStatsGetDumpReply::RecycleCached(val) => {
7725 if last_off == offset {
7726 stack.push(("RecycleCached", last_off));
7727 break;
7728 }
7729 }
7730 OpPagePoolStatsGetDumpReply::RecycleCacheFull(val) => {
7731 if last_off == offset {
7732 stack.push(("RecycleCacheFull", last_off));
7733 break;
7734 }
7735 }
7736 OpPagePoolStatsGetDumpReply::RecycleRing(val) => {
7737 if last_off == offset {
7738 stack.push(("RecycleRing", last_off));
7739 break;
7740 }
7741 }
7742 OpPagePoolStatsGetDumpReply::RecycleRingFull(val) => {
7743 if last_off == offset {
7744 stack.push(("RecycleRingFull", last_off));
7745 break;
7746 }
7747 }
7748 OpPagePoolStatsGetDumpReply::RecycleReleasedRefcnt(val) => {
7749 if last_off == offset {
7750 stack.push(("RecycleReleasedRefcnt", last_off));
7751 break;
7752 }
7753 }
7754 _ => {}
7755 };
7756 last_off = cur + attrs.pos;
7757 }
7758 if !stack.is_empty() {
7759 stack.push(("OpPagePoolStatsGetDumpReply", cur));
7760 }
7761 (stack, missing)
7762 }
7763}
7764#[derive(Debug)]
7765pub struct RequestOpPagePoolStatsGetDumpRequest<'r> {
7766 request: Request<'r>,
7767}
7768impl<'r> RequestOpPagePoolStatsGetDumpRequest<'r> {
7769 pub fn new(mut request: Request<'r>) -> Self {
7770 PushOpPagePoolStatsGetDumpRequest::write_header(&mut request.buf_mut());
7771 Self {
7772 request: request.set_dump(),
7773 }
7774 }
7775 pub fn encode(&mut self) -> PushOpPagePoolStatsGetDumpRequest<&mut Vec<u8>> {
7776 PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf_mut())
7777 }
7778 pub fn into_encoder(self) -> PushOpPagePoolStatsGetDumpRequest<RequestBuf<'r>> {
7779 PushOpPagePoolStatsGetDumpRequest::new_without_header(self.request.buf)
7780 }
7781}
7782impl NetlinkRequest for RequestOpPagePoolStatsGetDumpRequest<'_> {
7783 type ReplyType<'buf> = IterableOpPagePoolStatsGetDumpReply<'buf>;
7784 fn protocol(&self) -> Protocol {
7785 Protocol::Generic("netdev".as_bytes())
7786 }
7787 fn flags(&self) -> u16 {
7788 self.request.flags
7789 }
7790 fn payload(&self) -> &[u8] {
7791 self.request.buf()
7792 }
7793 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
7794 OpPagePoolStatsGetDumpReply::new(buf)
7795 }
7796 fn lookup(
7797 buf: &[u8],
7798 offset: usize,
7799 missing_type: Option<u16>,
7800 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7801 OpPagePoolStatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
7802 }
7803}
7804#[doc = "Get page pool statistics."]
7805pub struct PushOpPagePoolStatsGetDoRequest<Prev: Rec> {
7806 pub(crate) prev: Option<Prev>,
7807 pub(crate) header_offset: Option<usize>,
7808}
7809impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoRequest<Prev> {
7810 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
7811 self.prev.as_mut().unwrap().as_rec_mut()
7812 }
7813}
7814impl<Prev: Rec> PushOpPagePoolStatsGetDoRequest<Prev> {
7815 pub fn new(mut prev: Prev) -> Self {
7816 Self::write_header(&mut prev);
7817 Self::new_without_header(prev)
7818 }
7819 fn new_without_header(prev: Prev) -> Self {
7820 Self {
7821 prev: Some(prev),
7822 header_offset: None,
7823 }
7824 }
7825 fn write_header(prev: &mut Prev) {
7826 let mut header = PushBuiltinNfgenmsg::new();
7827 header.set_cmd(9u8);
7828 header.set_version(1u8);
7829 prev.as_rec_mut().extend(header.as_slice());
7830 }
7831 pub fn end_nested(mut self) -> Prev {
7832 let mut prev = self.prev.take().unwrap();
7833 if let Some(header_offset) = &self.header_offset {
7834 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7835 }
7836 prev
7837 }
7838 #[doc = "Page pool identifying information."]
7839 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
7840 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
7841 PushPagePoolInfo {
7842 prev: Some(self),
7843 header_offset: Some(header_offset),
7844 }
7845 }
7846}
7847impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoRequest<Prev> {
7848 fn drop(&mut self) {
7849 if let Some(prev) = &mut self.prev {
7850 if let Some(header_offset) = &self.header_offset {
7851 finalize_nested_header(prev.as_rec_mut(), *header_offset);
7852 }
7853 }
7854 }
7855}
7856#[doc = "Get page pool statistics."]
7857#[derive(Clone)]
7858pub enum OpPagePoolStatsGetDoRequest<'a> {
7859 #[doc = "Page pool identifying information."]
7860 Info(IterablePagePoolInfo<'a>),
7861}
7862impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7863 #[doc = "Page pool identifying information."]
7864 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
7865 let mut iter = self.clone();
7866 iter.pos = 0;
7867 for attr in iter {
7868 if let OpPagePoolStatsGetDoRequest::Info(val) = attr? {
7869 return Ok(val);
7870 }
7871 }
7872 Err(ErrorContext::new_missing(
7873 "OpPagePoolStatsGetDoRequest",
7874 "Info",
7875 self.orig_loc,
7876 self.buf.as_ptr() as usize,
7877 ))
7878 }
7879}
7880impl OpPagePoolStatsGetDoRequest<'_> {
7881 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoRequest<'a> {
7882 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
7883 IterableOpPagePoolStatsGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
7884 }
7885 fn attr_from_type(r#type: u16) -> Option<&'static str> {
7886 PagePoolStats::attr_from_type(r#type)
7887 }
7888}
7889#[derive(Clone, Copy, Default)]
7890pub struct IterableOpPagePoolStatsGetDoRequest<'a> {
7891 buf: &'a [u8],
7892 pos: usize,
7893 orig_loc: usize,
7894}
7895impl<'a> IterableOpPagePoolStatsGetDoRequest<'a> {
7896 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
7897 Self {
7898 buf,
7899 pos: 0,
7900 orig_loc,
7901 }
7902 }
7903 pub fn get_buf(&self) -> &'a [u8] {
7904 self.buf
7905 }
7906}
7907impl<'a> Iterator for IterableOpPagePoolStatsGetDoRequest<'a> {
7908 type Item = Result<OpPagePoolStatsGetDoRequest<'a>, ErrorContext>;
7909 fn next(&mut self) -> Option<Self::Item> {
7910 if self.buf.len() == self.pos {
7911 return None;
7912 }
7913 let pos = self.pos;
7914 let mut r#type = None;
7915 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
7916 r#type = Some(header.r#type);
7917 let res = match header.r#type {
7918 1u16 => OpPagePoolStatsGetDoRequest::Info({
7919 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
7920 let Some(val) = res else { break };
7921 val
7922 }),
7923 n => {
7924 if cfg!(any(test, feature = "deny-unknown-attrs")) {
7925 break;
7926 } else {
7927 continue;
7928 }
7929 }
7930 };
7931 return Some(Ok(res));
7932 }
7933 Some(Err(ErrorContext::new(
7934 "OpPagePoolStatsGetDoRequest",
7935 r#type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7936 self.orig_loc,
7937 self.buf.as_ptr().wrapping_add(pos) as usize,
7938 )))
7939 }
7940}
7941impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoRequest<'_> {
7942 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7943 let mut fmt = f.debug_struct("OpPagePoolStatsGetDoRequest");
7944 for attr in self.clone() {
7945 let attr = match attr {
7946 Ok(a) => a,
7947 Err(err) => {
7948 fmt.finish()?;
7949 f.write_str("Err(")?;
7950 err.fmt(f)?;
7951 return f.write_str(")");
7952 }
7953 };
7954 match attr {
7955 OpPagePoolStatsGetDoRequest::Info(val) => fmt.field("Info", &val),
7956 };
7957 }
7958 fmt.finish()
7959 }
7960}
7961impl IterableOpPagePoolStatsGetDoRequest<'_> {
7962 pub fn lookup_attr(
7963 &self,
7964 offset: usize,
7965 missing_type: Option<u16>,
7966 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
7967 let mut stack = Vec::new();
7968 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
7969 if cur == offset + PushBuiltinNfgenmsg::len() {
7970 stack.push(("OpPagePoolStatsGetDoRequest", offset));
7971 return (
7972 stack,
7973 missing_type.and_then(|t| OpPagePoolStatsGetDoRequest::attr_from_type(t)),
7974 );
7975 }
7976 if cur > offset || cur + self.buf.len() < offset {
7977 return (stack, None);
7978 }
7979 let mut attrs = self.clone();
7980 let mut last_off = cur + attrs.pos;
7981 let mut missing = None;
7982 while let Some(attr) = attrs.next() {
7983 let Ok(attr) = attr else { break };
7984 match attr {
7985 OpPagePoolStatsGetDoRequest::Info(val) => {
7986 (stack, missing) = val.lookup_attr(offset, missing_type);
7987 if !stack.is_empty() {
7988 break;
7989 }
7990 }
7991 _ => {}
7992 };
7993 last_off = cur + attrs.pos;
7994 }
7995 if !stack.is_empty() {
7996 stack.push(("OpPagePoolStatsGetDoRequest", cur));
7997 }
7998 (stack, missing)
7999 }
8000}
8001#[doc = "Get page pool statistics."]
8002pub struct PushOpPagePoolStatsGetDoReply<Prev: Rec> {
8003 pub(crate) prev: Option<Prev>,
8004 pub(crate) header_offset: Option<usize>,
8005}
8006impl<Prev: Rec> Rec for PushOpPagePoolStatsGetDoReply<Prev> {
8007 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8008 self.prev.as_mut().unwrap().as_rec_mut()
8009 }
8010}
8011impl<Prev: Rec> PushOpPagePoolStatsGetDoReply<Prev> {
8012 pub fn new(mut prev: Prev) -> Self {
8013 Self::write_header(&mut prev);
8014 Self::new_without_header(prev)
8015 }
8016 fn new_without_header(prev: Prev) -> Self {
8017 Self {
8018 prev: Some(prev),
8019 header_offset: None,
8020 }
8021 }
8022 fn write_header(prev: &mut Prev) {
8023 let mut header = PushBuiltinNfgenmsg::new();
8024 header.set_cmd(9u8);
8025 header.set_version(1u8);
8026 prev.as_rec_mut().extend(header.as_slice());
8027 }
8028 pub fn end_nested(mut self) -> Prev {
8029 let mut prev = self.prev.take().unwrap();
8030 if let Some(header_offset) = &self.header_offset {
8031 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8032 }
8033 prev
8034 }
8035 #[doc = "Page pool identifying information."]
8036 pub fn nested_info(mut self) -> PushPagePoolInfo<Self> {
8037 let header_offset = push_nested_header(self.as_rec_mut(), 1u16);
8038 PushPagePoolInfo {
8039 prev: Some(self),
8040 header_offset: Some(header_offset),
8041 }
8042 }
8043 pub fn push_alloc_fast(mut self, value: u32) -> Self {
8044 push_header(self.as_rec_mut(), 8u16, 4 as u16);
8045 self.as_rec_mut().extend(value.to_ne_bytes());
8046 self
8047 }
8048 pub fn push_alloc_slow(mut self, value: u32) -> Self {
8049 push_header(self.as_rec_mut(), 9u16, 4 as u16);
8050 self.as_rec_mut().extend(value.to_ne_bytes());
8051 self
8052 }
8053 pub fn push_alloc_slow_high_order(mut self, value: u32) -> Self {
8054 push_header(self.as_rec_mut(), 10u16, 4 as u16);
8055 self.as_rec_mut().extend(value.to_ne_bytes());
8056 self
8057 }
8058 pub fn push_alloc_empty(mut self, value: u32) -> Self {
8059 push_header(self.as_rec_mut(), 11u16, 4 as u16);
8060 self.as_rec_mut().extend(value.to_ne_bytes());
8061 self
8062 }
8063 pub fn push_alloc_refill(mut self, value: u32) -> Self {
8064 push_header(self.as_rec_mut(), 12u16, 4 as u16);
8065 self.as_rec_mut().extend(value.to_ne_bytes());
8066 self
8067 }
8068 pub fn push_alloc_waive(mut self, value: u32) -> Self {
8069 push_header(self.as_rec_mut(), 13u16, 4 as u16);
8070 self.as_rec_mut().extend(value.to_ne_bytes());
8071 self
8072 }
8073 pub fn push_recycle_cached(mut self, value: u32) -> Self {
8074 push_header(self.as_rec_mut(), 14u16, 4 as u16);
8075 self.as_rec_mut().extend(value.to_ne_bytes());
8076 self
8077 }
8078 pub fn push_recycle_cache_full(mut self, value: u32) -> Self {
8079 push_header(self.as_rec_mut(), 15u16, 4 as u16);
8080 self.as_rec_mut().extend(value.to_ne_bytes());
8081 self
8082 }
8083 pub fn push_recycle_ring(mut self, value: u32) -> Self {
8084 push_header(self.as_rec_mut(), 16u16, 4 as u16);
8085 self.as_rec_mut().extend(value.to_ne_bytes());
8086 self
8087 }
8088 pub fn push_recycle_ring_full(mut self, value: u32) -> Self {
8089 push_header(self.as_rec_mut(), 17u16, 4 as u16);
8090 self.as_rec_mut().extend(value.to_ne_bytes());
8091 self
8092 }
8093 pub fn push_recycle_released_refcnt(mut self, value: u32) -> Self {
8094 push_header(self.as_rec_mut(), 18u16, 4 as u16);
8095 self.as_rec_mut().extend(value.to_ne_bytes());
8096 self
8097 }
8098}
8099impl<Prev: Rec> Drop for PushOpPagePoolStatsGetDoReply<Prev> {
8100 fn drop(&mut self) {
8101 if let Some(prev) = &mut self.prev {
8102 if let Some(header_offset) = &self.header_offset {
8103 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8104 }
8105 }
8106 }
8107}
8108#[doc = "Get page pool statistics."]
8109#[derive(Clone)]
8110pub enum OpPagePoolStatsGetDoReply<'a> {
8111 #[doc = "Page pool identifying information."]
8112 Info(IterablePagePoolInfo<'a>),
8113 AllocFast(u32),
8114 AllocSlow(u32),
8115 AllocSlowHighOrder(u32),
8116 AllocEmpty(u32),
8117 AllocRefill(u32),
8118 AllocWaive(u32),
8119 RecycleCached(u32),
8120 RecycleCacheFull(u32),
8121 RecycleRing(u32),
8122 RecycleRingFull(u32),
8123 RecycleReleasedRefcnt(u32),
8124}
8125impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8126 #[doc = "Page pool identifying information."]
8127 pub fn get_info(&self) -> Result<IterablePagePoolInfo<'a>, ErrorContext> {
8128 let mut iter = self.clone();
8129 iter.pos = 0;
8130 for attr in iter {
8131 if let OpPagePoolStatsGetDoReply::Info(val) = attr? {
8132 return Ok(val);
8133 }
8134 }
8135 Err(ErrorContext::new_missing(
8136 "OpPagePoolStatsGetDoReply",
8137 "Info",
8138 self.orig_loc,
8139 self.buf.as_ptr() as usize,
8140 ))
8141 }
8142 pub fn get_alloc_fast(&self) -> Result<u32, ErrorContext> {
8143 let mut iter = self.clone();
8144 iter.pos = 0;
8145 for attr in iter {
8146 if let OpPagePoolStatsGetDoReply::AllocFast(val) = attr? {
8147 return Ok(val);
8148 }
8149 }
8150 Err(ErrorContext::new_missing(
8151 "OpPagePoolStatsGetDoReply",
8152 "AllocFast",
8153 self.orig_loc,
8154 self.buf.as_ptr() as usize,
8155 ))
8156 }
8157 pub fn get_alloc_slow(&self) -> Result<u32, ErrorContext> {
8158 let mut iter = self.clone();
8159 iter.pos = 0;
8160 for attr in iter {
8161 if let OpPagePoolStatsGetDoReply::AllocSlow(val) = attr? {
8162 return Ok(val);
8163 }
8164 }
8165 Err(ErrorContext::new_missing(
8166 "OpPagePoolStatsGetDoReply",
8167 "AllocSlow",
8168 self.orig_loc,
8169 self.buf.as_ptr() as usize,
8170 ))
8171 }
8172 pub fn get_alloc_slow_high_order(&self) -> Result<u32, ErrorContext> {
8173 let mut iter = self.clone();
8174 iter.pos = 0;
8175 for attr in iter {
8176 if let OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) = attr? {
8177 return Ok(val);
8178 }
8179 }
8180 Err(ErrorContext::new_missing(
8181 "OpPagePoolStatsGetDoReply",
8182 "AllocSlowHighOrder",
8183 self.orig_loc,
8184 self.buf.as_ptr() as usize,
8185 ))
8186 }
8187 pub fn get_alloc_empty(&self) -> Result<u32, ErrorContext> {
8188 let mut iter = self.clone();
8189 iter.pos = 0;
8190 for attr in iter {
8191 if let OpPagePoolStatsGetDoReply::AllocEmpty(val) = attr? {
8192 return Ok(val);
8193 }
8194 }
8195 Err(ErrorContext::new_missing(
8196 "OpPagePoolStatsGetDoReply",
8197 "AllocEmpty",
8198 self.orig_loc,
8199 self.buf.as_ptr() as usize,
8200 ))
8201 }
8202 pub fn get_alloc_refill(&self) -> Result<u32, ErrorContext> {
8203 let mut iter = self.clone();
8204 iter.pos = 0;
8205 for attr in iter {
8206 if let OpPagePoolStatsGetDoReply::AllocRefill(val) = attr? {
8207 return Ok(val);
8208 }
8209 }
8210 Err(ErrorContext::new_missing(
8211 "OpPagePoolStatsGetDoReply",
8212 "AllocRefill",
8213 self.orig_loc,
8214 self.buf.as_ptr() as usize,
8215 ))
8216 }
8217 pub fn get_alloc_waive(&self) -> Result<u32, ErrorContext> {
8218 let mut iter = self.clone();
8219 iter.pos = 0;
8220 for attr in iter {
8221 if let OpPagePoolStatsGetDoReply::AllocWaive(val) = attr? {
8222 return Ok(val);
8223 }
8224 }
8225 Err(ErrorContext::new_missing(
8226 "OpPagePoolStatsGetDoReply",
8227 "AllocWaive",
8228 self.orig_loc,
8229 self.buf.as_ptr() as usize,
8230 ))
8231 }
8232 pub fn get_recycle_cached(&self) -> Result<u32, ErrorContext> {
8233 let mut iter = self.clone();
8234 iter.pos = 0;
8235 for attr in iter {
8236 if let OpPagePoolStatsGetDoReply::RecycleCached(val) = attr? {
8237 return Ok(val);
8238 }
8239 }
8240 Err(ErrorContext::new_missing(
8241 "OpPagePoolStatsGetDoReply",
8242 "RecycleCached",
8243 self.orig_loc,
8244 self.buf.as_ptr() as usize,
8245 ))
8246 }
8247 pub fn get_recycle_cache_full(&self) -> Result<u32, ErrorContext> {
8248 let mut iter = self.clone();
8249 iter.pos = 0;
8250 for attr in iter {
8251 if let OpPagePoolStatsGetDoReply::RecycleCacheFull(val) = attr? {
8252 return Ok(val);
8253 }
8254 }
8255 Err(ErrorContext::new_missing(
8256 "OpPagePoolStatsGetDoReply",
8257 "RecycleCacheFull",
8258 self.orig_loc,
8259 self.buf.as_ptr() as usize,
8260 ))
8261 }
8262 pub fn get_recycle_ring(&self) -> Result<u32, ErrorContext> {
8263 let mut iter = self.clone();
8264 iter.pos = 0;
8265 for attr in iter {
8266 if let OpPagePoolStatsGetDoReply::RecycleRing(val) = attr? {
8267 return Ok(val);
8268 }
8269 }
8270 Err(ErrorContext::new_missing(
8271 "OpPagePoolStatsGetDoReply",
8272 "RecycleRing",
8273 self.orig_loc,
8274 self.buf.as_ptr() as usize,
8275 ))
8276 }
8277 pub fn get_recycle_ring_full(&self) -> Result<u32, ErrorContext> {
8278 let mut iter = self.clone();
8279 iter.pos = 0;
8280 for attr in iter {
8281 if let OpPagePoolStatsGetDoReply::RecycleRingFull(val) = attr? {
8282 return Ok(val);
8283 }
8284 }
8285 Err(ErrorContext::new_missing(
8286 "OpPagePoolStatsGetDoReply",
8287 "RecycleRingFull",
8288 self.orig_loc,
8289 self.buf.as_ptr() as usize,
8290 ))
8291 }
8292 pub fn get_recycle_released_refcnt(&self) -> Result<u32, ErrorContext> {
8293 let mut iter = self.clone();
8294 iter.pos = 0;
8295 for attr in iter {
8296 if let OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) = attr? {
8297 return Ok(val);
8298 }
8299 }
8300 Err(ErrorContext::new_missing(
8301 "OpPagePoolStatsGetDoReply",
8302 "RecycleReleasedRefcnt",
8303 self.orig_loc,
8304 self.buf.as_ptr() as usize,
8305 ))
8306 }
8307}
8308impl OpPagePoolStatsGetDoReply<'_> {
8309 pub fn new<'a>(buf: &'a [u8]) -> IterableOpPagePoolStatsGetDoReply<'a> {
8310 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8311 IterableOpPagePoolStatsGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
8312 }
8313 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8314 PagePoolStats::attr_from_type(r#type)
8315 }
8316}
8317#[derive(Clone, Copy, Default)]
8318pub struct IterableOpPagePoolStatsGetDoReply<'a> {
8319 buf: &'a [u8],
8320 pos: usize,
8321 orig_loc: usize,
8322}
8323impl<'a> IterableOpPagePoolStatsGetDoReply<'a> {
8324 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8325 Self {
8326 buf,
8327 pos: 0,
8328 orig_loc,
8329 }
8330 }
8331 pub fn get_buf(&self) -> &'a [u8] {
8332 self.buf
8333 }
8334}
8335impl<'a> Iterator for IterableOpPagePoolStatsGetDoReply<'a> {
8336 type Item = Result<OpPagePoolStatsGetDoReply<'a>, ErrorContext>;
8337 fn next(&mut self) -> Option<Self::Item> {
8338 if self.buf.len() == self.pos {
8339 return None;
8340 }
8341 let pos = self.pos;
8342 let mut r#type = None;
8343 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
8344 r#type = Some(header.r#type);
8345 let res = match header.r#type {
8346 1u16 => OpPagePoolStatsGetDoReply::Info({
8347 let res = Some(IterablePagePoolInfo::with_loc(next, self.orig_loc));
8348 let Some(val) = res else { break };
8349 val
8350 }),
8351 8u16 => OpPagePoolStatsGetDoReply::AllocFast({
8352 let res = parse_u32(next);
8353 let Some(val) = res else { break };
8354 val
8355 }),
8356 9u16 => OpPagePoolStatsGetDoReply::AllocSlow({
8357 let res = parse_u32(next);
8358 let Some(val) = res else { break };
8359 val
8360 }),
8361 10u16 => OpPagePoolStatsGetDoReply::AllocSlowHighOrder({
8362 let res = parse_u32(next);
8363 let Some(val) = res else { break };
8364 val
8365 }),
8366 11u16 => OpPagePoolStatsGetDoReply::AllocEmpty({
8367 let res = parse_u32(next);
8368 let Some(val) = res else { break };
8369 val
8370 }),
8371 12u16 => OpPagePoolStatsGetDoReply::AllocRefill({
8372 let res = parse_u32(next);
8373 let Some(val) = res else { break };
8374 val
8375 }),
8376 13u16 => OpPagePoolStatsGetDoReply::AllocWaive({
8377 let res = parse_u32(next);
8378 let Some(val) = res else { break };
8379 val
8380 }),
8381 14u16 => OpPagePoolStatsGetDoReply::RecycleCached({
8382 let res = parse_u32(next);
8383 let Some(val) = res else { break };
8384 val
8385 }),
8386 15u16 => OpPagePoolStatsGetDoReply::RecycleCacheFull({
8387 let res = parse_u32(next);
8388 let Some(val) = res else { break };
8389 val
8390 }),
8391 16u16 => OpPagePoolStatsGetDoReply::RecycleRing({
8392 let res = parse_u32(next);
8393 let Some(val) = res else { break };
8394 val
8395 }),
8396 17u16 => OpPagePoolStatsGetDoReply::RecycleRingFull({
8397 let res = parse_u32(next);
8398 let Some(val) = res else { break };
8399 val
8400 }),
8401 18u16 => OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt({
8402 let res = parse_u32(next);
8403 let Some(val) = res else { break };
8404 val
8405 }),
8406 n => {
8407 if cfg!(any(test, feature = "deny-unknown-attrs")) {
8408 break;
8409 } else {
8410 continue;
8411 }
8412 }
8413 };
8414 return Some(Ok(res));
8415 }
8416 Some(Err(ErrorContext::new(
8417 "OpPagePoolStatsGetDoReply",
8418 r#type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8419 self.orig_loc,
8420 self.buf.as_ptr().wrapping_add(pos) as usize,
8421 )))
8422 }
8423}
8424impl<'a> std::fmt::Debug for IterableOpPagePoolStatsGetDoReply<'_> {
8425 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8426 let mut fmt = f.debug_struct("OpPagePoolStatsGetDoReply");
8427 for attr in self.clone() {
8428 let attr = match attr {
8429 Ok(a) => a,
8430 Err(err) => {
8431 fmt.finish()?;
8432 f.write_str("Err(")?;
8433 err.fmt(f)?;
8434 return f.write_str(")");
8435 }
8436 };
8437 match attr {
8438 OpPagePoolStatsGetDoReply::Info(val) => fmt.field("Info", &val),
8439 OpPagePoolStatsGetDoReply::AllocFast(val) => fmt.field("AllocFast", &val),
8440 OpPagePoolStatsGetDoReply::AllocSlow(val) => fmt.field("AllocSlow", &val),
8441 OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8442 fmt.field("AllocSlowHighOrder", &val)
8443 }
8444 OpPagePoolStatsGetDoReply::AllocEmpty(val) => fmt.field("AllocEmpty", &val),
8445 OpPagePoolStatsGetDoReply::AllocRefill(val) => fmt.field("AllocRefill", &val),
8446 OpPagePoolStatsGetDoReply::AllocWaive(val) => fmt.field("AllocWaive", &val),
8447 OpPagePoolStatsGetDoReply::RecycleCached(val) => fmt.field("RecycleCached", &val),
8448 OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8449 fmt.field("RecycleCacheFull", &val)
8450 }
8451 OpPagePoolStatsGetDoReply::RecycleRing(val) => fmt.field("RecycleRing", &val),
8452 OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8453 fmt.field("RecycleRingFull", &val)
8454 }
8455 OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8456 fmt.field("RecycleReleasedRefcnt", &val)
8457 }
8458 };
8459 }
8460 fmt.finish()
8461 }
8462}
8463impl IterableOpPagePoolStatsGetDoReply<'_> {
8464 pub fn lookup_attr(
8465 &self,
8466 offset: usize,
8467 missing_type: Option<u16>,
8468 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8469 let mut stack = Vec::new();
8470 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8471 if cur == offset + PushBuiltinNfgenmsg::len() {
8472 stack.push(("OpPagePoolStatsGetDoReply", offset));
8473 return (
8474 stack,
8475 missing_type.and_then(|t| OpPagePoolStatsGetDoReply::attr_from_type(t)),
8476 );
8477 }
8478 if cur > offset || cur + self.buf.len() < offset {
8479 return (stack, None);
8480 }
8481 let mut attrs = self.clone();
8482 let mut last_off = cur + attrs.pos;
8483 let mut missing = None;
8484 while let Some(attr) = attrs.next() {
8485 let Ok(attr) = attr else { break };
8486 match attr {
8487 OpPagePoolStatsGetDoReply::Info(val) => {
8488 (stack, missing) = val.lookup_attr(offset, missing_type);
8489 if !stack.is_empty() {
8490 break;
8491 }
8492 }
8493 OpPagePoolStatsGetDoReply::AllocFast(val) => {
8494 if last_off == offset {
8495 stack.push(("AllocFast", last_off));
8496 break;
8497 }
8498 }
8499 OpPagePoolStatsGetDoReply::AllocSlow(val) => {
8500 if last_off == offset {
8501 stack.push(("AllocSlow", last_off));
8502 break;
8503 }
8504 }
8505 OpPagePoolStatsGetDoReply::AllocSlowHighOrder(val) => {
8506 if last_off == offset {
8507 stack.push(("AllocSlowHighOrder", last_off));
8508 break;
8509 }
8510 }
8511 OpPagePoolStatsGetDoReply::AllocEmpty(val) => {
8512 if last_off == offset {
8513 stack.push(("AllocEmpty", last_off));
8514 break;
8515 }
8516 }
8517 OpPagePoolStatsGetDoReply::AllocRefill(val) => {
8518 if last_off == offset {
8519 stack.push(("AllocRefill", last_off));
8520 break;
8521 }
8522 }
8523 OpPagePoolStatsGetDoReply::AllocWaive(val) => {
8524 if last_off == offset {
8525 stack.push(("AllocWaive", last_off));
8526 break;
8527 }
8528 }
8529 OpPagePoolStatsGetDoReply::RecycleCached(val) => {
8530 if last_off == offset {
8531 stack.push(("RecycleCached", last_off));
8532 break;
8533 }
8534 }
8535 OpPagePoolStatsGetDoReply::RecycleCacheFull(val) => {
8536 if last_off == offset {
8537 stack.push(("RecycleCacheFull", last_off));
8538 break;
8539 }
8540 }
8541 OpPagePoolStatsGetDoReply::RecycleRing(val) => {
8542 if last_off == offset {
8543 stack.push(("RecycleRing", last_off));
8544 break;
8545 }
8546 }
8547 OpPagePoolStatsGetDoReply::RecycleRingFull(val) => {
8548 if last_off == offset {
8549 stack.push(("RecycleRingFull", last_off));
8550 break;
8551 }
8552 }
8553 OpPagePoolStatsGetDoReply::RecycleReleasedRefcnt(val) => {
8554 if last_off == offset {
8555 stack.push(("RecycleReleasedRefcnt", last_off));
8556 break;
8557 }
8558 }
8559 _ => {}
8560 };
8561 last_off = cur + attrs.pos;
8562 }
8563 if !stack.is_empty() {
8564 stack.push(("OpPagePoolStatsGetDoReply", cur));
8565 }
8566 (stack, missing)
8567 }
8568}
8569#[derive(Debug)]
8570pub struct RequestOpPagePoolStatsGetDoRequest<'r> {
8571 request: Request<'r>,
8572}
8573impl<'r> RequestOpPagePoolStatsGetDoRequest<'r> {
8574 pub fn new(mut request: Request<'r>) -> Self {
8575 PushOpPagePoolStatsGetDoRequest::write_header(&mut request.buf_mut());
8576 Self { request: request }
8577 }
8578 pub fn encode(&mut self) -> PushOpPagePoolStatsGetDoRequest<&mut Vec<u8>> {
8579 PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf_mut())
8580 }
8581 pub fn into_encoder(self) -> PushOpPagePoolStatsGetDoRequest<RequestBuf<'r>> {
8582 PushOpPagePoolStatsGetDoRequest::new_without_header(self.request.buf)
8583 }
8584}
8585impl NetlinkRequest for RequestOpPagePoolStatsGetDoRequest<'_> {
8586 type ReplyType<'buf> = IterableOpPagePoolStatsGetDoReply<'buf>;
8587 fn protocol(&self) -> Protocol {
8588 Protocol::Generic("netdev".as_bytes())
8589 }
8590 fn flags(&self) -> u16 {
8591 self.request.flags
8592 }
8593 fn payload(&self) -> &[u8] {
8594 self.request.buf()
8595 }
8596 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
8597 OpPagePoolStatsGetDoReply::new(buf)
8598 }
8599 fn lookup(
8600 buf: &[u8],
8601 offset: usize,
8602 missing_type: Option<u16>,
8603 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8604 OpPagePoolStatsGetDoRequest::new(buf).lookup_attr(offset, missing_type)
8605 }
8606}
8607#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8608pub struct PushOpQueueGetDumpRequest<Prev: Rec> {
8609 pub(crate) prev: Option<Prev>,
8610 pub(crate) header_offset: Option<usize>,
8611}
8612impl<Prev: Rec> Rec for PushOpQueueGetDumpRequest<Prev> {
8613 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8614 self.prev.as_mut().unwrap().as_rec_mut()
8615 }
8616}
8617impl<Prev: Rec> PushOpQueueGetDumpRequest<Prev> {
8618 pub fn new(mut prev: Prev) -> Self {
8619 Self::write_header(&mut prev);
8620 Self::new_without_header(prev)
8621 }
8622 fn new_without_header(prev: Prev) -> Self {
8623 Self {
8624 prev: Some(prev),
8625 header_offset: None,
8626 }
8627 }
8628 fn write_header(prev: &mut Prev) {
8629 let mut header = PushBuiltinNfgenmsg::new();
8630 header.set_cmd(10u8);
8631 header.set_version(1u8);
8632 prev.as_rec_mut().extend(header.as_slice());
8633 }
8634 pub fn end_nested(mut self) -> Prev {
8635 let mut prev = self.prev.take().unwrap();
8636 if let Some(header_offset) = &self.header_offset {
8637 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8638 }
8639 prev
8640 }
8641 #[doc = "ifindex of the netdevice to which the queue belongs."]
8642 pub fn push_ifindex(mut self, value: u32) -> Self {
8643 push_header(self.as_rec_mut(), 2u16, 4 as u16);
8644 self.as_rec_mut().extend(value.to_ne_bytes());
8645 self
8646 }
8647}
8648impl<Prev: Rec> Drop for PushOpQueueGetDumpRequest<Prev> {
8649 fn drop(&mut self) {
8650 if let Some(prev) = &mut self.prev {
8651 if let Some(header_offset) = &self.header_offset {
8652 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8653 }
8654 }
8655 }
8656}
8657#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8658#[derive(Clone)]
8659pub enum OpQueueGetDumpRequest {
8660 #[doc = "ifindex of the netdevice to which the queue belongs."]
8661 Ifindex(u32),
8662}
8663impl<'a> IterableOpQueueGetDumpRequest<'a> {
8664 #[doc = "ifindex of the netdevice to which the queue belongs."]
8665 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8666 let mut iter = self.clone();
8667 iter.pos = 0;
8668 for attr in iter {
8669 if let OpQueueGetDumpRequest::Ifindex(val) = attr? {
8670 return Ok(val);
8671 }
8672 }
8673 Err(ErrorContext::new_missing(
8674 "OpQueueGetDumpRequest",
8675 "Ifindex",
8676 self.orig_loc,
8677 self.buf.as_ptr() as usize,
8678 ))
8679 }
8680}
8681impl OpQueueGetDumpRequest {
8682 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpRequest<'a> {
8683 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
8684 IterableOpQueueGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
8685 }
8686 fn attr_from_type(r#type: u16) -> Option<&'static str> {
8687 Queue::attr_from_type(r#type)
8688 }
8689}
8690#[derive(Clone, Copy, Default)]
8691pub struct IterableOpQueueGetDumpRequest<'a> {
8692 buf: &'a [u8],
8693 pos: usize,
8694 orig_loc: usize,
8695}
8696impl<'a> IterableOpQueueGetDumpRequest<'a> {
8697 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
8698 Self {
8699 buf,
8700 pos: 0,
8701 orig_loc,
8702 }
8703 }
8704 pub fn get_buf(&self) -> &'a [u8] {
8705 self.buf
8706 }
8707}
8708impl<'a> Iterator for IterableOpQueueGetDumpRequest<'a> {
8709 type Item = Result<OpQueueGetDumpRequest, ErrorContext>;
8710 fn next(&mut self) -> Option<Self::Item> {
8711 if self.buf.len() == self.pos {
8712 return None;
8713 }
8714 let pos = self.pos;
8715 let mut r#type = None;
8716 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
8717 r#type = Some(header.r#type);
8718 let res = match header.r#type {
8719 2u16 => OpQueueGetDumpRequest::Ifindex({
8720 let res = parse_u32(next);
8721 let Some(val) = res else { break };
8722 val
8723 }),
8724 n => {
8725 if cfg!(any(test, feature = "deny-unknown-attrs")) {
8726 break;
8727 } else {
8728 continue;
8729 }
8730 }
8731 };
8732 return Some(Ok(res));
8733 }
8734 Some(Err(ErrorContext::new(
8735 "OpQueueGetDumpRequest",
8736 r#type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8737 self.orig_loc,
8738 self.buf.as_ptr().wrapping_add(pos) as usize,
8739 )))
8740 }
8741}
8742impl std::fmt::Debug for IterableOpQueueGetDumpRequest<'_> {
8743 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8744 let mut fmt = f.debug_struct("OpQueueGetDumpRequest");
8745 for attr in self.clone() {
8746 let attr = match attr {
8747 Ok(a) => a,
8748 Err(err) => {
8749 fmt.finish()?;
8750 f.write_str("Err(")?;
8751 err.fmt(f)?;
8752 return f.write_str(")");
8753 }
8754 };
8755 match attr {
8756 OpQueueGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
8757 };
8758 }
8759 fmt.finish()
8760 }
8761}
8762impl IterableOpQueueGetDumpRequest<'_> {
8763 pub fn lookup_attr(
8764 &self,
8765 offset: usize,
8766 missing_type: Option<u16>,
8767 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
8768 let mut stack = Vec::new();
8769 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
8770 if cur == offset + PushBuiltinNfgenmsg::len() {
8771 stack.push(("OpQueueGetDumpRequest", offset));
8772 return (
8773 stack,
8774 missing_type.and_then(|t| OpQueueGetDumpRequest::attr_from_type(t)),
8775 );
8776 }
8777 if cur > offset || cur + self.buf.len() < offset {
8778 return (stack, None);
8779 }
8780 let mut attrs = self.clone();
8781 let mut last_off = cur + attrs.pos;
8782 while let Some(attr) = attrs.next() {
8783 let Ok(attr) = attr else { break };
8784 match attr {
8785 OpQueueGetDumpRequest::Ifindex(val) => {
8786 if last_off == offset {
8787 stack.push(("Ifindex", last_off));
8788 break;
8789 }
8790 }
8791 _ => {}
8792 };
8793 last_off = cur + attrs.pos;
8794 }
8795 if !stack.is_empty() {
8796 stack.push(("OpQueueGetDumpRequest", cur));
8797 }
8798 (stack, None)
8799 }
8800}
8801#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8802pub struct PushOpQueueGetDumpReply<Prev: Rec> {
8803 pub(crate) prev: Option<Prev>,
8804 pub(crate) header_offset: Option<usize>,
8805}
8806impl<Prev: Rec> Rec for PushOpQueueGetDumpReply<Prev> {
8807 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
8808 self.prev.as_mut().unwrap().as_rec_mut()
8809 }
8810}
8811impl<Prev: Rec> PushOpQueueGetDumpReply<Prev> {
8812 pub fn new(mut prev: Prev) -> Self {
8813 Self::write_header(&mut prev);
8814 Self::new_without_header(prev)
8815 }
8816 fn new_without_header(prev: Prev) -> Self {
8817 Self {
8818 prev: Some(prev),
8819 header_offset: None,
8820 }
8821 }
8822 fn write_header(prev: &mut Prev) {
8823 let mut header = PushBuiltinNfgenmsg::new();
8824 header.set_cmd(10u8);
8825 header.set_version(1u8);
8826 prev.as_rec_mut().extend(header.as_slice());
8827 }
8828 pub fn end_nested(mut self) -> Prev {
8829 let mut prev = self.prev.take().unwrap();
8830 if let Some(header_offset) = &self.header_offset {
8831 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8832 }
8833 prev
8834 }
8835 #[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."]
8836 pub fn push_id(mut self, value: u32) -> Self {
8837 push_header(self.as_rec_mut(), 1u16, 4 as u16);
8838 self.as_rec_mut().extend(value.to_ne_bytes());
8839 self
8840 }
8841 #[doc = "ifindex of the netdevice to which the queue belongs."]
8842 pub fn push_ifindex(mut self, value: u32) -> Self {
8843 push_header(self.as_rec_mut(), 2u16, 4 as u16);
8844 self.as_rec_mut().extend(value.to_ne_bytes());
8845 self
8846 }
8847 #[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)"]
8848 pub fn push_type(mut self, value: u32) -> Self {
8849 push_header(self.as_rec_mut(), 3u16, 4 as u16);
8850 self.as_rec_mut().extend(value.to_ne_bytes());
8851 self
8852 }
8853 #[doc = "ID of the NAPI instance which services this queue."]
8854 pub fn push_napi_id(mut self, value: u32) -> Self {
8855 push_header(self.as_rec_mut(), 4u16, 4 as u16);
8856 self.as_rec_mut().extend(value.to_ne_bytes());
8857 self
8858 }
8859 #[doc = "ID of the dmabuf attached to this queue, if any."]
8860 pub fn push_dmabuf(mut self, value: u32) -> Self {
8861 push_header(self.as_rec_mut(), 5u16, 4 as u16);
8862 self.as_rec_mut().extend(value.to_ne_bytes());
8863 self
8864 }
8865 #[doc = "io_uring memory provider information."]
8866 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
8867 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
8868 PushIoUringProviderInfo {
8869 prev: Some(self),
8870 header_offset: Some(header_offset),
8871 }
8872 }
8873 #[doc = "XSK information for this queue, if any."]
8874 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
8875 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
8876 PushXskInfo {
8877 prev: Some(self),
8878 header_offset: Some(header_offset),
8879 }
8880 }
8881}
8882impl<Prev: Rec> Drop for PushOpQueueGetDumpReply<Prev> {
8883 fn drop(&mut self) {
8884 if let Some(prev) = &mut self.prev {
8885 if let Some(header_offset) = &self.header_offset {
8886 finalize_nested_header(prev.as_rec_mut(), *header_offset);
8887 }
8888 }
8889 }
8890}
8891#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
8892#[derive(Clone)]
8893pub enum OpQueueGetDumpReply<'a> {
8894 #[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."]
8895 Id(u32),
8896 #[doc = "ifindex of the netdevice to which the queue belongs."]
8897 Ifindex(u32),
8898 #[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)"]
8899 Type(u32),
8900 #[doc = "ID of the NAPI instance which services this queue."]
8901 NapiId(u32),
8902 #[doc = "ID of the dmabuf attached to this queue, if any."]
8903 Dmabuf(u32),
8904 #[doc = "io_uring memory provider information."]
8905 IoUring(IterableIoUringProviderInfo<'a>),
8906 #[doc = "XSK information for this queue, if any."]
8907 Xsk(IterableXskInfo<'a>),
8908}
8909impl<'a> IterableOpQueueGetDumpReply<'a> {
8910 #[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."]
8911 pub fn get_id(&self) -> Result<u32, ErrorContext> {
8912 let mut iter = self.clone();
8913 iter.pos = 0;
8914 for attr in iter {
8915 if let OpQueueGetDumpReply::Id(val) = attr? {
8916 return Ok(val);
8917 }
8918 }
8919 Err(ErrorContext::new_missing(
8920 "OpQueueGetDumpReply",
8921 "Id",
8922 self.orig_loc,
8923 self.buf.as_ptr() as usize,
8924 ))
8925 }
8926 #[doc = "ifindex of the netdevice to which the queue belongs."]
8927 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
8928 let mut iter = self.clone();
8929 iter.pos = 0;
8930 for attr in iter {
8931 if let OpQueueGetDumpReply::Ifindex(val) = attr? {
8932 return Ok(val);
8933 }
8934 }
8935 Err(ErrorContext::new_missing(
8936 "OpQueueGetDumpReply",
8937 "Ifindex",
8938 self.orig_loc,
8939 self.buf.as_ptr() as usize,
8940 ))
8941 }
8942 #[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)"]
8943 pub fn get_type(&self) -> Result<u32, ErrorContext> {
8944 let mut iter = self.clone();
8945 iter.pos = 0;
8946 for attr in iter {
8947 if let OpQueueGetDumpReply::Type(val) = attr? {
8948 return Ok(val);
8949 }
8950 }
8951 Err(ErrorContext::new_missing(
8952 "OpQueueGetDumpReply",
8953 "Type",
8954 self.orig_loc,
8955 self.buf.as_ptr() as usize,
8956 ))
8957 }
8958 #[doc = "ID of the NAPI instance which services this queue."]
8959 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
8960 let mut iter = self.clone();
8961 iter.pos = 0;
8962 for attr in iter {
8963 if let OpQueueGetDumpReply::NapiId(val) = attr? {
8964 return Ok(val);
8965 }
8966 }
8967 Err(ErrorContext::new_missing(
8968 "OpQueueGetDumpReply",
8969 "NapiId",
8970 self.orig_loc,
8971 self.buf.as_ptr() as usize,
8972 ))
8973 }
8974 #[doc = "ID of the dmabuf attached to this queue, if any."]
8975 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
8976 let mut iter = self.clone();
8977 iter.pos = 0;
8978 for attr in iter {
8979 if let OpQueueGetDumpReply::Dmabuf(val) = attr? {
8980 return Ok(val);
8981 }
8982 }
8983 Err(ErrorContext::new_missing(
8984 "OpQueueGetDumpReply",
8985 "Dmabuf",
8986 self.orig_loc,
8987 self.buf.as_ptr() as usize,
8988 ))
8989 }
8990 #[doc = "io_uring memory provider information."]
8991 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
8992 let mut iter = self.clone();
8993 iter.pos = 0;
8994 for attr in iter {
8995 if let OpQueueGetDumpReply::IoUring(val) = attr? {
8996 return Ok(val);
8997 }
8998 }
8999 Err(ErrorContext::new_missing(
9000 "OpQueueGetDumpReply",
9001 "IoUring",
9002 self.orig_loc,
9003 self.buf.as_ptr() as usize,
9004 ))
9005 }
9006 #[doc = "XSK information for this queue, if any."]
9007 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9008 let mut iter = self.clone();
9009 iter.pos = 0;
9010 for attr in iter {
9011 if let OpQueueGetDumpReply::Xsk(val) = attr? {
9012 return Ok(val);
9013 }
9014 }
9015 Err(ErrorContext::new_missing(
9016 "OpQueueGetDumpReply",
9017 "Xsk",
9018 self.orig_loc,
9019 self.buf.as_ptr() as usize,
9020 ))
9021 }
9022}
9023impl OpQueueGetDumpReply<'_> {
9024 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDumpReply<'a> {
9025 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9026 IterableOpQueueGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
9027 }
9028 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9029 Queue::attr_from_type(r#type)
9030 }
9031}
9032#[derive(Clone, Copy, Default)]
9033pub struct IterableOpQueueGetDumpReply<'a> {
9034 buf: &'a [u8],
9035 pos: usize,
9036 orig_loc: usize,
9037}
9038impl<'a> IterableOpQueueGetDumpReply<'a> {
9039 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9040 Self {
9041 buf,
9042 pos: 0,
9043 orig_loc,
9044 }
9045 }
9046 pub fn get_buf(&self) -> &'a [u8] {
9047 self.buf
9048 }
9049}
9050impl<'a> Iterator for IterableOpQueueGetDumpReply<'a> {
9051 type Item = Result<OpQueueGetDumpReply<'a>, ErrorContext>;
9052 fn next(&mut self) -> Option<Self::Item> {
9053 if self.buf.len() == self.pos {
9054 return None;
9055 }
9056 let pos = self.pos;
9057 let mut r#type = None;
9058 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9059 r#type = Some(header.r#type);
9060 let res = match header.r#type {
9061 1u16 => OpQueueGetDumpReply::Id({
9062 let res = parse_u32(next);
9063 let Some(val) = res else { break };
9064 val
9065 }),
9066 2u16 => OpQueueGetDumpReply::Ifindex({
9067 let res = parse_u32(next);
9068 let Some(val) = res else { break };
9069 val
9070 }),
9071 3u16 => OpQueueGetDumpReply::Type({
9072 let res = parse_u32(next);
9073 let Some(val) = res else { break };
9074 val
9075 }),
9076 4u16 => OpQueueGetDumpReply::NapiId({
9077 let res = parse_u32(next);
9078 let Some(val) = res else { break };
9079 val
9080 }),
9081 5u16 => OpQueueGetDumpReply::Dmabuf({
9082 let res = parse_u32(next);
9083 let Some(val) = res else { break };
9084 val
9085 }),
9086 6u16 => OpQueueGetDumpReply::IoUring({
9087 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9088 let Some(val) = res else { break };
9089 val
9090 }),
9091 7u16 => OpQueueGetDumpReply::Xsk({
9092 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9093 let Some(val) = res else { break };
9094 val
9095 }),
9096 n => {
9097 if cfg!(any(test, feature = "deny-unknown-attrs")) {
9098 break;
9099 } else {
9100 continue;
9101 }
9102 }
9103 };
9104 return Some(Ok(res));
9105 }
9106 Some(Err(ErrorContext::new(
9107 "OpQueueGetDumpReply",
9108 r#type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9109 self.orig_loc,
9110 self.buf.as_ptr().wrapping_add(pos) as usize,
9111 )))
9112 }
9113}
9114impl<'a> std::fmt::Debug for IterableOpQueueGetDumpReply<'_> {
9115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9116 let mut fmt = f.debug_struct("OpQueueGetDumpReply");
9117 for attr in self.clone() {
9118 let attr = match attr {
9119 Ok(a) => a,
9120 Err(err) => {
9121 fmt.finish()?;
9122 f.write_str("Err(")?;
9123 err.fmt(f)?;
9124 return f.write_str(")");
9125 }
9126 };
9127 match attr {
9128 OpQueueGetDumpReply::Id(val) => fmt.field("Id", &val),
9129 OpQueueGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
9130 OpQueueGetDumpReply::Type(val) => {
9131 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9132 }
9133 OpQueueGetDumpReply::NapiId(val) => fmt.field("NapiId", &val),
9134 OpQueueGetDumpReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9135 OpQueueGetDumpReply::IoUring(val) => fmt.field("IoUring", &val),
9136 OpQueueGetDumpReply::Xsk(val) => fmt.field("Xsk", &val),
9137 };
9138 }
9139 fmt.finish()
9140 }
9141}
9142impl IterableOpQueueGetDumpReply<'_> {
9143 pub fn lookup_attr(
9144 &self,
9145 offset: usize,
9146 missing_type: Option<u16>,
9147 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9148 let mut stack = Vec::new();
9149 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9150 if cur == offset + PushBuiltinNfgenmsg::len() {
9151 stack.push(("OpQueueGetDumpReply", offset));
9152 return (
9153 stack,
9154 missing_type.and_then(|t| OpQueueGetDumpReply::attr_from_type(t)),
9155 );
9156 }
9157 if cur > offset || cur + self.buf.len() < offset {
9158 return (stack, None);
9159 }
9160 let mut attrs = self.clone();
9161 let mut last_off = cur + attrs.pos;
9162 let mut missing = None;
9163 while let Some(attr) = attrs.next() {
9164 let Ok(attr) = attr else { break };
9165 match attr {
9166 OpQueueGetDumpReply::Id(val) => {
9167 if last_off == offset {
9168 stack.push(("Id", last_off));
9169 break;
9170 }
9171 }
9172 OpQueueGetDumpReply::Ifindex(val) => {
9173 if last_off == offset {
9174 stack.push(("Ifindex", last_off));
9175 break;
9176 }
9177 }
9178 OpQueueGetDumpReply::Type(val) => {
9179 if last_off == offset {
9180 stack.push(("Type", last_off));
9181 break;
9182 }
9183 }
9184 OpQueueGetDumpReply::NapiId(val) => {
9185 if last_off == offset {
9186 stack.push(("NapiId", last_off));
9187 break;
9188 }
9189 }
9190 OpQueueGetDumpReply::Dmabuf(val) => {
9191 if last_off == offset {
9192 stack.push(("Dmabuf", last_off));
9193 break;
9194 }
9195 }
9196 OpQueueGetDumpReply::IoUring(val) => {
9197 (stack, missing) = val.lookup_attr(offset, missing_type);
9198 if !stack.is_empty() {
9199 break;
9200 }
9201 }
9202 OpQueueGetDumpReply::Xsk(val) => {
9203 (stack, missing) = val.lookup_attr(offset, missing_type);
9204 if !stack.is_empty() {
9205 break;
9206 }
9207 }
9208 _ => {}
9209 };
9210 last_off = cur + attrs.pos;
9211 }
9212 if !stack.is_empty() {
9213 stack.push(("OpQueueGetDumpReply", cur));
9214 }
9215 (stack, missing)
9216 }
9217}
9218#[derive(Debug)]
9219pub struct RequestOpQueueGetDumpRequest<'r> {
9220 request: Request<'r>,
9221}
9222impl<'r> RequestOpQueueGetDumpRequest<'r> {
9223 pub fn new(mut request: Request<'r>) -> Self {
9224 PushOpQueueGetDumpRequest::write_header(&mut request.buf_mut());
9225 Self {
9226 request: request.set_dump(),
9227 }
9228 }
9229 pub fn encode(&mut self) -> PushOpQueueGetDumpRequest<&mut Vec<u8>> {
9230 PushOpQueueGetDumpRequest::new_without_header(self.request.buf_mut())
9231 }
9232 pub fn into_encoder(self) -> PushOpQueueGetDumpRequest<RequestBuf<'r>> {
9233 PushOpQueueGetDumpRequest::new_without_header(self.request.buf)
9234 }
9235}
9236impl NetlinkRequest for RequestOpQueueGetDumpRequest<'_> {
9237 type ReplyType<'buf> = IterableOpQueueGetDumpReply<'buf>;
9238 fn protocol(&self) -> Protocol {
9239 Protocol::Generic("netdev".as_bytes())
9240 }
9241 fn flags(&self) -> u16 {
9242 self.request.flags
9243 }
9244 fn payload(&self) -> &[u8] {
9245 self.request.buf()
9246 }
9247 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9248 OpQueueGetDumpReply::new(buf)
9249 }
9250 fn lookup(
9251 buf: &[u8],
9252 offset: usize,
9253 missing_type: Option<u16>,
9254 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9255 OpQueueGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
9256 }
9257}
9258#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9259pub struct PushOpQueueGetDoRequest<Prev: Rec> {
9260 pub(crate) prev: Option<Prev>,
9261 pub(crate) header_offset: Option<usize>,
9262}
9263impl<Prev: Rec> Rec for PushOpQueueGetDoRequest<Prev> {
9264 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9265 self.prev.as_mut().unwrap().as_rec_mut()
9266 }
9267}
9268impl<Prev: Rec> PushOpQueueGetDoRequest<Prev> {
9269 pub fn new(mut prev: Prev) -> Self {
9270 Self::write_header(&mut prev);
9271 Self::new_without_header(prev)
9272 }
9273 fn new_without_header(prev: Prev) -> Self {
9274 Self {
9275 prev: Some(prev),
9276 header_offset: None,
9277 }
9278 }
9279 fn write_header(prev: &mut Prev) {
9280 let mut header = PushBuiltinNfgenmsg::new();
9281 header.set_cmd(10u8);
9282 header.set_version(1u8);
9283 prev.as_rec_mut().extend(header.as_slice());
9284 }
9285 pub fn end_nested(mut self) -> Prev {
9286 let mut prev = self.prev.take().unwrap();
9287 if let Some(header_offset) = &self.header_offset {
9288 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9289 }
9290 prev
9291 }
9292 #[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."]
9293 pub fn push_id(mut self, value: u32) -> Self {
9294 push_header(self.as_rec_mut(), 1u16, 4 as u16);
9295 self.as_rec_mut().extend(value.to_ne_bytes());
9296 self
9297 }
9298 #[doc = "ifindex of the netdevice to which the queue belongs."]
9299 pub fn push_ifindex(mut self, value: u32) -> Self {
9300 push_header(self.as_rec_mut(), 2u16, 4 as u16);
9301 self.as_rec_mut().extend(value.to_ne_bytes());
9302 self
9303 }
9304 #[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)"]
9305 pub fn push_type(mut self, value: u32) -> Self {
9306 push_header(self.as_rec_mut(), 3u16, 4 as u16);
9307 self.as_rec_mut().extend(value.to_ne_bytes());
9308 self
9309 }
9310}
9311impl<Prev: Rec> Drop for PushOpQueueGetDoRequest<Prev> {
9312 fn drop(&mut self) {
9313 if let Some(prev) = &mut self.prev {
9314 if let Some(header_offset) = &self.header_offset {
9315 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9316 }
9317 }
9318 }
9319}
9320#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9321#[derive(Clone)]
9322pub enum OpQueueGetDoRequest {
9323 #[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."]
9324 Id(u32),
9325 #[doc = "ifindex of the netdevice to which the queue belongs."]
9326 Ifindex(u32),
9327 #[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)"]
9328 Type(u32),
9329}
9330impl<'a> IterableOpQueueGetDoRequest<'a> {
9331 #[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."]
9332 pub fn get_id(&self) -> Result<u32, ErrorContext> {
9333 let mut iter = self.clone();
9334 iter.pos = 0;
9335 for attr in iter {
9336 if let OpQueueGetDoRequest::Id(val) = attr? {
9337 return Ok(val);
9338 }
9339 }
9340 Err(ErrorContext::new_missing(
9341 "OpQueueGetDoRequest",
9342 "Id",
9343 self.orig_loc,
9344 self.buf.as_ptr() as usize,
9345 ))
9346 }
9347 #[doc = "ifindex of the netdevice to which the queue belongs."]
9348 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9349 let mut iter = self.clone();
9350 iter.pos = 0;
9351 for attr in iter {
9352 if let OpQueueGetDoRequest::Ifindex(val) = attr? {
9353 return Ok(val);
9354 }
9355 }
9356 Err(ErrorContext::new_missing(
9357 "OpQueueGetDoRequest",
9358 "Ifindex",
9359 self.orig_loc,
9360 self.buf.as_ptr() as usize,
9361 ))
9362 }
9363 #[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)"]
9364 pub fn get_type(&self) -> Result<u32, ErrorContext> {
9365 let mut iter = self.clone();
9366 iter.pos = 0;
9367 for attr in iter {
9368 if let OpQueueGetDoRequest::Type(val) = attr? {
9369 return Ok(val);
9370 }
9371 }
9372 Err(ErrorContext::new_missing(
9373 "OpQueueGetDoRequest",
9374 "Type",
9375 self.orig_loc,
9376 self.buf.as_ptr() as usize,
9377 ))
9378 }
9379}
9380impl OpQueueGetDoRequest {
9381 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoRequest<'a> {
9382 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9383 IterableOpQueueGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
9384 }
9385 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9386 Queue::attr_from_type(r#type)
9387 }
9388}
9389#[derive(Clone, Copy, Default)]
9390pub struct IterableOpQueueGetDoRequest<'a> {
9391 buf: &'a [u8],
9392 pos: usize,
9393 orig_loc: usize,
9394}
9395impl<'a> IterableOpQueueGetDoRequest<'a> {
9396 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9397 Self {
9398 buf,
9399 pos: 0,
9400 orig_loc,
9401 }
9402 }
9403 pub fn get_buf(&self) -> &'a [u8] {
9404 self.buf
9405 }
9406}
9407impl<'a> Iterator for IterableOpQueueGetDoRequest<'a> {
9408 type Item = Result<OpQueueGetDoRequest, ErrorContext>;
9409 fn next(&mut self) -> Option<Self::Item> {
9410 if self.buf.len() == self.pos {
9411 return None;
9412 }
9413 let pos = self.pos;
9414 let mut r#type = None;
9415 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9416 r#type = Some(header.r#type);
9417 let res = match header.r#type {
9418 1u16 => OpQueueGetDoRequest::Id({
9419 let res = parse_u32(next);
9420 let Some(val) = res else { break };
9421 val
9422 }),
9423 2u16 => OpQueueGetDoRequest::Ifindex({
9424 let res = parse_u32(next);
9425 let Some(val) = res else { break };
9426 val
9427 }),
9428 3u16 => OpQueueGetDoRequest::Type({
9429 let res = parse_u32(next);
9430 let Some(val) = res else { break };
9431 val
9432 }),
9433 n => {
9434 if cfg!(any(test, feature = "deny-unknown-attrs")) {
9435 break;
9436 } else {
9437 continue;
9438 }
9439 }
9440 };
9441 return Some(Ok(res));
9442 }
9443 Some(Err(ErrorContext::new(
9444 "OpQueueGetDoRequest",
9445 r#type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9446 self.orig_loc,
9447 self.buf.as_ptr().wrapping_add(pos) as usize,
9448 )))
9449 }
9450}
9451impl std::fmt::Debug for IterableOpQueueGetDoRequest<'_> {
9452 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9453 let mut fmt = f.debug_struct("OpQueueGetDoRequest");
9454 for attr in self.clone() {
9455 let attr = match attr {
9456 Ok(a) => a,
9457 Err(err) => {
9458 fmt.finish()?;
9459 f.write_str("Err(")?;
9460 err.fmt(f)?;
9461 return f.write_str(")");
9462 }
9463 };
9464 match attr {
9465 OpQueueGetDoRequest::Id(val) => fmt.field("Id", &val),
9466 OpQueueGetDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
9467 OpQueueGetDoRequest::Type(val) => {
9468 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9469 }
9470 };
9471 }
9472 fmt.finish()
9473 }
9474}
9475impl IterableOpQueueGetDoRequest<'_> {
9476 pub fn lookup_attr(
9477 &self,
9478 offset: usize,
9479 missing_type: Option<u16>,
9480 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9481 let mut stack = Vec::new();
9482 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9483 if cur == offset + PushBuiltinNfgenmsg::len() {
9484 stack.push(("OpQueueGetDoRequest", offset));
9485 return (
9486 stack,
9487 missing_type.and_then(|t| OpQueueGetDoRequest::attr_from_type(t)),
9488 );
9489 }
9490 if cur > offset || cur + self.buf.len() < offset {
9491 return (stack, None);
9492 }
9493 let mut attrs = self.clone();
9494 let mut last_off = cur + attrs.pos;
9495 while let Some(attr) = attrs.next() {
9496 let Ok(attr) = attr else { break };
9497 match attr {
9498 OpQueueGetDoRequest::Id(val) => {
9499 if last_off == offset {
9500 stack.push(("Id", last_off));
9501 break;
9502 }
9503 }
9504 OpQueueGetDoRequest::Ifindex(val) => {
9505 if last_off == offset {
9506 stack.push(("Ifindex", last_off));
9507 break;
9508 }
9509 }
9510 OpQueueGetDoRequest::Type(val) => {
9511 if last_off == offset {
9512 stack.push(("Type", last_off));
9513 break;
9514 }
9515 }
9516 _ => {}
9517 };
9518 last_off = cur + attrs.pos;
9519 }
9520 if !stack.is_empty() {
9521 stack.push(("OpQueueGetDoRequest", cur));
9522 }
9523 (stack, None)
9524 }
9525}
9526#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9527pub struct PushOpQueueGetDoReply<Prev: Rec> {
9528 pub(crate) prev: Option<Prev>,
9529 pub(crate) header_offset: Option<usize>,
9530}
9531impl<Prev: Rec> Rec for PushOpQueueGetDoReply<Prev> {
9532 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9533 self.prev.as_mut().unwrap().as_rec_mut()
9534 }
9535}
9536impl<Prev: Rec> PushOpQueueGetDoReply<Prev> {
9537 pub fn new(mut prev: Prev) -> Self {
9538 Self::write_header(&mut prev);
9539 Self::new_without_header(prev)
9540 }
9541 fn new_without_header(prev: Prev) -> Self {
9542 Self {
9543 prev: Some(prev),
9544 header_offset: None,
9545 }
9546 }
9547 fn write_header(prev: &mut Prev) {
9548 let mut header = PushBuiltinNfgenmsg::new();
9549 header.set_cmd(10u8);
9550 header.set_version(1u8);
9551 prev.as_rec_mut().extend(header.as_slice());
9552 }
9553 pub fn end_nested(mut self) -> Prev {
9554 let mut prev = self.prev.take().unwrap();
9555 if let Some(header_offset) = &self.header_offset {
9556 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9557 }
9558 prev
9559 }
9560 #[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."]
9561 pub fn push_id(mut self, value: u32) -> Self {
9562 push_header(self.as_rec_mut(), 1u16, 4 as u16);
9563 self.as_rec_mut().extend(value.to_ne_bytes());
9564 self
9565 }
9566 #[doc = "ifindex of the netdevice to which the queue belongs."]
9567 pub fn push_ifindex(mut self, value: u32) -> Self {
9568 push_header(self.as_rec_mut(), 2u16, 4 as u16);
9569 self.as_rec_mut().extend(value.to_ne_bytes());
9570 self
9571 }
9572 #[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)"]
9573 pub fn push_type(mut self, value: u32) -> Self {
9574 push_header(self.as_rec_mut(), 3u16, 4 as u16);
9575 self.as_rec_mut().extend(value.to_ne_bytes());
9576 self
9577 }
9578 #[doc = "ID of the NAPI instance which services this queue."]
9579 pub fn push_napi_id(mut self, value: u32) -> Self {
9580 push_header(self.as_rec_mut(), 4u16, 4 as u16);
9581 self.as_rec_mut().extend(value.to_ne_bytes());
9582 self
9583 }
9584 #[doc = "ID of the dmabuf attached to this queue, if any."]
9585 pub fn push_dmabuf(mut self, value: u32) -> Self {
9586 push_header(self.as_rec_mut(), 5u16, 4 as u16);
9587 self.as_rec_mut().extend(value.to_ne_bytes());
9588 self
9589 }
9590 #[doc = "io_uring memory provider information."]
9591 pub fn nested_io_uring(mut self) -> PushIoUringProviderInfo<Self> {
9592 let header_offset = push_nested_header(self.as_rec_mut(), 6u16);
9593 PushIoUringProviderInfo {
9594 prev: Some(self),
9595 header_offset: Some(header_offset),
9596 }
9597 }
9598 #[doc = "XSK information for this queue, if any."]
9599 pub fn nested_xsk(mut self) -> PushXskInfo<Self> {
9600 let header_offset = push_nested_header(self.as_rec_mut(), 7u16);
9601 PushXskInfo {
9602 prev: Some(self),
9603 header_offset: Some(header_offset),
9604 }
9605 }
9606}
9607impl<Prev: Rec> Drop for PushOpQueueGetDoReply<Prev> {
9608 fn drop(&mut self) {
9609 if let Some(prev) = &mut self.prev {
9610 if let Some(header_offset) = &self.header_offset {
9611 finalize_nested_header(prev.as_rec_mut(), *header_offset);
9612 }
9613 }
9614 }
9615}
9616#[doc = "Get queue information from the kernel. Only configured queues will be reported (as opposed to all available hardware queues)."]
9617#[derive(Clone)]
9618pub enum OpQueueGetDoReply<'a> {
9619 #[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."]
9620 Id(u32),
9621 #[doc = "ifindex of the netdevice to which the queue belongs."]
9622 Ifindex(u32),
9623 #[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)"]
9624 Type(u32),
9625 #[doc = "ID of the NAPI instance which services this queue."]
9626 NapiId(u32),
9627 #[doc = "ID of the dmabuf attached to this queue, if any."]
9628 Dmabuf(u32),
9629 #[doc = "io_uring memory provider information."]
9630 IoUring(IterableIoUringProviderInfo<'a>),
9631 #[doc = "XSK information for this queue, if any."]
9632 Xsk(IterableXskInfo<'a>),
9633}
9634impl<'a> IterableOpQueueGetDoReply<'a> {
9635 #[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."]
9636 pub fn get_id(&self) -> Result<u32, ErrorContext> {
9637 let mut iter = self.clone();
9638 iter.pos = 0;
9639 for attr in iter {
9640 if let OpQueueGetDoReply::Id(val) = attr? {
9641 return Ok(val);
9642 }
9643 }
9644 Err(ErrorContext::new_missing(
9645 "OpQueueGetDoReply",
9646 "Id",
9647 self.orig_loc,
9648 self.buf.as_ptr() as usize,
9649 ))
9650 }
9651 #[doc = "ifindex of the netdevice to which the queue belongs."]
9652 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
9653 let mut iter = self.clone();
9654 iter.pos = 0;
9655 for attr in iter {
9656 if let OpQueueGetDoReply::Ifindex(val) = attr? {
9657 return Ok(val);
9658 }
9659 }
9660 Err(ErrorContext::new_missing(
9661 "OpQueueGetDoReply",
9662 "Ifindex",
9663 self.orig_loc,
9664 self.buf.as_ptr() as usize,
9665 ))
9666 }
9667 #[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)"]
9668 pub fn get_type(&self) -> Result<u32, ErrorContext> {
9669 let mut iter = self.clone();
9670 iter.pos = 0;
9671 for attr in iter {
9672 if let OpQueueGetDoReply::Type(val) = attr? {
9673 return Ok(val);
9674 }
9675 }
9676 Err(ErrorContext::new_missing(
9677 "OpQueueGetDoReply",
9678 "Type",
9679 self.orig_loc,
9680 self.buf.as_ptr() as usize,
9681 ))
9682 }
9683 #[doc = "ID of the NAPI instance which services this queue."]
9684 pub fn get_napi_id(&self) -> Result<u32, ErrorContext> {
9685 let mut iter = self.clone();
9686 iter.pos = 0;
9687 for attr in iter {
9688 if let OpQueueGetDoReply::NapiId(val) = attr? {
9689 return Ok(val);
9690 }
9691 }
9692 Err(ErrorContext::new_missing(
9693 "OpQueueGetDoReply",
9694 "NapiId",
9695 self.orig_loc,
9696 self.buf.as_ptr() as usize,
9697 ))
9698 }
9699 #[doc = "ID of the dmabuf attached to this queue, if any."]
9700 pub fn get_dmabuf(&self) -> Result<u32, ErrorContext> {
9701 let mut iter = self.clone();
9702 iter.pos = 0;
9703 for attr in iter {
9704 if let OpQueueGetDoReply::Dmabuf(val) = attr? {
9705 return Ok(val);
9706 }
9707 }
9708 Err(ErrorContext::new_missing(
9709 "OpQueueGetDoReply",
9710 "Dmabuf",
9711 self.orig_loc,
9712 self.buf.as_ptr() as usize,
9713 ))
9714 }
9715 #[doc = "io_uring memory provider information."]
9716 pub fn get_io_uring(&self) -> Result<IterableIoUringProviderInfo<'a>, ErrorContext> {
9717 let mut iter = self.clone();
9718 iter.pos = 0;
9719 for attr in iter {
9720 if let OpQueueGetDoReply::IoUring(val) = attr? {
9721 return Ok(val);
9722 }
9723 }
9724 Err(ErrorContext::new_missing(
9725 "OpQueueGetDoReply",
9726 "IoUring",
9727 self.orig_loc,
9728 self.buf.as_ptr() as usize,
9729 ))
9730 }
9731 #[doc = "XSK information for this queue, if any."]
9732 pub fn get_xsk(&self) -> Result<IterableXskInfo<'a>, ErrorContext> {
9733 let mut iter = self.clone();
9734 iter.pos = 0;
9735 for attr in iter {
9736 if let OpQueueGetDoReply::Xsk(val) = attr? {
9737 return Ok(val);
9738 }
9739 }
9740 Err(ErrorContext::new_missing(
9741 "OpQueueGetDoReply",
9742 "Xsk",
9743 self.orig_loc,
9744 self.buf.as_ptr() as usize,
9745 ))
9746 }
9747}
9748impl OpQueueGetDoReply<'_> {
9749 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQueueGetDoReply<'a> {
9750 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
9751 IterableOpQueueGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
9752 }
9753 fn attr_from_type(r#type: u16) -> Option<&'static str> {
9754 Queue::attr_from_type(r#type)
9755 }
9756}
9757#[derive(Clone, Copy, Default)]
9758pub struct IterableOpQueueGetDoReply<'a> {
9759 buf: &'a [u8],
9760 pos: usize,
9761 orig_loc: usize,
9762}
9763impl<'a> IterableOpQueueGetDoReply<'a> {
9764 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
9765 Self {
9766 buf,
9767 pos: 0,
9768 orig_loc,
9769 }
9770 }
9771 pub fn get_buf(&self) -> &'a [u8] {
9772 self.buf
9773 }
9774}
9775impl<'a> Iterator for IterableOpQueueGetDoReply<'a> {
9776 type Item = Result<OpQueueGetDoReply<'a>, ErrorContext>;
9777 fn next(&mut self) -> Option<Self::Item> {
9778 if self.buf.len() == self.pos {
9779 return None;
9780 }
9781 let pos = self.pos;
9782 let mut r#type = None;
9783 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
9784 r#type = Some(header.r#type);
9785 let res = match header.r#type {
9786 1u16 => OpQueueGetDoReply::Id({
9787 let res = parse_u32(next);
9788 let Some(val) = res else { break };
9789 val
9790 }),
9791 2u16 => OpQueueGetDoReply::Ifindex({
9792 let res = parse_u32(next);
9793 let Some(val) = res else { break };
9794 val
9795 }),
9796 3u16 => OpQueueGetDoReply::Type({
9797 let res = parse_u32(next);
9798 let Some(val) = res else { break };
9799 val
9800 }),
9801 4u16 => OpQueueGetDoReply::NapiId({
9802 let res = parse_u32(next);
9803 let Some(val) = res else { break };
9804 val
9805 }),
9806 5u16 => OpQueueGetDoReply::Dmabuf({
9807 let res = parse_u32(next);
9808 let Some(val) = res else { break };
9809 val
9810 }),
9811 6u16 => OpQueueGetDoReply::IoUring({
9812 let res = Some(IterableIoUringProviderInfo::with_loc(next, self.orig_loc));
9813 let Some(val) = res else { break };
9814 val
9815 }),
9816 7u16 => OpQueueGetDoReply::Xsk({
9817 let res = Some(IterableXskInfo::with_loc(next, self.orig_loc));
9818 let Some(val) = res else { break };
9819 val
9820 }),
9821 n => {
9822 if cfg!(any(test, feature = "deny-unknown-attrs")) {
9823 break;
9824 } else {
9825 continue;
9826 }
9827 }
9828 };
9829 return Some(Ok(res));
9830 }
9831 Some(Err(ErrorContext::new(
9832 "OpQueueGetDoReply",
9833 r#type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9834 self.orig_loc,
9835 self.buf.as_ptr().wrapping_add(pos) as usize,
9836 )))
9837 }
9838}
9839impl<'a> std::fmt::Debug for IterableOpQueueGetDoReply<'_> {
9840 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9841 let mut fmt = f.debug_struct("OpQueueGetDoReply");
9842 for attr in self.clone() {
9843 let attr = match attr {
9844 Ok(a) => a,
9845 Err(err) => {
9846 fmt.finish()?;
9847 f.write_str("Err(")?;
9848 err.fmt(f)?;
9849 return f.write_str(")");
9850 }
9851 };
9852 match attr {
9853 OpQueueGetDoReply::Id(val) => fmt.field("Id", &val),
9854 OpQueueGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
9855 OpQueueGetDoReply::Type(val) => {
9856 fmt.field("Type", &FormatEnum(val.into(), QueueType::from_value))
9857 }
9858 OpQueueGetDoReply::NapiId(val) => fmt.field("NapiId", &val),
9859 OpQueueGetDoReply::Dmabuf(val) => fmt.field("Dmabuf", &val),
9860 OpQueueGetDoReply::IoUring(val) => fmt.field("IoUring", &val),
9861 OpQueueGetDoReply::Xsk(val) => fmt.field("Xsk", &val),
9862 };
9863 }
9864 fmt.finish()
9865 }
9866}
9867impl IterableOpQueueGetDoReply<'_> {
9868 pub fn lookup_attr(
9869 &self,
9870 offset: usize,
9871 missing_type: Option<u16>,
9872 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9873 let mut stack = Vec::new();
9874 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
9875 if cur == offset + PushBuiltinNfgenmsg::len() {
9876 stack.push(("OpQueueGetDoReply", offset));
9877 return (
9878 stack,
9879 missing_type.and_then(|t| OpQueueGetDoReply::attr_from_type(t)),
9880 );
9881 }
9882 if cur > offset || cur + self.buf.len() < offset {
9883 return (stack, None);
9884 }
9885 let mut attrs = self.clone();
9886 let mut last_off = cur + attrs.pos;
9887 let mut missing = None;
9888 while let Some(attr) = attrs.next() {
9889 let Ok(attr) = attr else { break };
9890 match attr {
9891 OpQueueGetDoReply::Id(val) => {
9892 if last_off == offset {
9893 stack.push(("Id", last_off));
9894 break;
9895 }
9896 }
9897 OpQueueGetDoReply::Ifindex(val) => {
9898 if last_off == offset {
9899 stack.push(("Ifindex", last_off));
9900 break;
9901 }
9902 }
9903 OpQueueGetDoReply::Type(val) => {
9904 if last_off == offset {
9905 stack.push(("Type", last_off));
9906 break;
9907 }
9908 }
9909 OpQueueGetDoReply::NapiId(val) => {
9910 if last_off == offset {
9911 stack.push(("NapiId", last_off));
9912 break;
9913 }
9914 }
9915 OpQueueGetDoReply::Dmabuf(val) => {
9916 if last_off == offset {
9917 stack.push(("Dmabuf", last_off));
9918 break;
9919 }
9920 }
9921 OpQueueGetDoReply::IoUring(val) => {
9922 (stack, missing) = val.lookup_attr(offset, missing_type);
9923 if !stack.is_empty() {
9924 break;
9925 }
9926 }
9927 OpQueueGetDoReply::Xsk(val) => {
9928 (stack, missing) = val.lookup_attr(offset, missing_type);
9929 if !stack.is_empty() {
9930 break;
9931 }
9932 }
9933 _ => {}
9934 };
9935 last_off = cur + attrs.pos;
9936 }
9937 if !stack.is_empty() {
9938 stack.push(("OpQueueGetDoReply", cur));
9939 }
9940 (stack, missing)
9941 }
9942}
9943#[derive(Debug)]
9944pub struct RequestOpQueueGetDoRequest<'r> {
9945 request: Request<'r>,
9946}
9947impl<'r> RequestOpQueueGetDoRequest<'r> {
9948 pub fn new(mut request: Request<'r>) -> Self {
9949 PushOpQueueGetDoRequest::write_header(&mut request.buf_mut());
9950 Self { request: request }
9951 }
9952 pub fn encode(&mut self) -> PushOpQueueGetDoRequest<&mut Vec<u8>> {
9953 PushOpQueueGetDoRequest::new_without_header(self.request.buf_mut())
9954 }
9955 pub fn into_encoder(self) -> PushOpQueueGetDoRequest<RequestBuf<'r>> {
9956 PushOpQueueGetDoRequest::new_without_header(self.request.buf)
9957 }
9958}
9959impl NetlinkRequest for RequestOpQueueGetDoRequest<'_> {
9960 type ReplyType<'buf> = IterableOpQueueGetDoReply<'buf>;
9961 fn protocol(&self) -> Protocol {
9962 Protocol::Generic("netdev".as_bytes())
9963 }
9964 fn flags(&self) -> u16 {
9965 self.request.flags
9966 }
9967 fn payload(&self) -> &[u8] {
9968 self.request.buf()
9969 }
9970 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
9971 OpQueueGetDoReply::new(buf)
9972 }
9973 fn lookup(
9974 buf: &[u8],
9975 offset: usize,
9976 missing_type: Option<u16>,
9977 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
9978 OpQueueGetDoRequest::new(buf).lookup_attr(offset, missing_type)
9979 }
9980}
9981#[doc = "Get information about NAPI instances configured on the system."]
9982pub struct PushOpNapiGetDumpRequest<Prev: Rec> {
9983 pub(crate) prev: Option<Prev>,
9984 pub(crate) header_offset: Option<usize>,
9985}
9986impl<Prev: Rec> Rec for PushOpNapiGetDumpRequest<Prev> {
9987 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
9988 self.prev.as_mut().unwrap().as_rec_mut()
9989 }
9990}
9991impl<Prev: Rec> PushOpNapiGetDumpRequest<Prev> {
9992 pub fn new(mut prev: Prev) -> Self {
9993 Self::write_header(&mut prev);
9994 Self::new_without_header(prev)
9995 }
9996 fn new_without_header(prev: Prev) -> Self {
9997 Self {
9998 prev: Some(prev),
9999 header_offset: None,
10000 }
10001 }
10002 fn write_header(prev: &mut Prev) {
10003 let mut header = PushBuiltinNfgenmsg::new();
10004 header.set_cmd(11u8);
10005 header.set_version(1u8);
10006 prev.as_rec_mut().extend(header.as_slice());
10007 }
10008 pub fn end_nested(mut self) -> Prev {
10009 let mut prev = self.prev.take().unwrap();
10010 if let Some(header_offset) = &self.header_offset {
10011 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10012 }
10013 prev
10014 }
10015 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10016 pub fn push_ifindex(mut self, value: u32) -> Self {
10017 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10018 self.as_rec_mut().extend(value.to_ne_bytes());
10019 self
10020 }
10021}
10022impl<Prev: Rec> Drop for PushOpNapiGetDumpRequest<Prev> {
10023 fn drop(&mut self) {
10024 if let Some(prev) = &mut self.prev {
10025 if let Some(header_offset) = &self.header_offset {
10026 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10027 }
10028 }
10029 }
10030}
10031#[doc = "Get information about NAPI instances configured on the system."]
10032#[derive(Clone)]
10033pub enum OpNapiGetDumpRequest {
10034 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10035 Ifindex(u32),
10036}
10037impl<'a> IterableOpNapiGetDumpRequest<'a> {
10038 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10039 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10040 let mut iter = self.clone();
10041 iter.pos = 0;
10042 for attr in iter {
10043 if let OpNapiGetDumpRequest::Ifindex(val) = attr? {
10044 return Ok(val);
10045 }
10046 }
10047 Err(ErrorContext::new_missing(
10048 "OpNapiGetDumpRequest",
10049 "Ifindex",
10050 self.orig_loc,
10051 self.buf.as_ptr() as usize,
10052 ))
10053 }
10054}
10055impl OpNapiGetDumpRequest {
10056 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpRequest<'a> {
10057 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10058 IterableOpNapiGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
10059 }
10060 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10061 Napi::attr_from_type(r#type)
10062 }
10063}
10064#[derive(Clone, Copy, Default)]
10065pub struct IterableOpNapiGetDumpRequest<'a> {
10066 buf: &'a [u8],
10067 pos: usize,
10068 orig_loc: usize,
10069}
10070impl<'a> IterableOpNapiGetDumpRequest<'a> {
10071 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10072 Self {
10073 buf,
10074 pos: 0,
10075 orig_loc,
10076 }
10077 }
10078 pub fn get_buf(&self) -> &'a [u8] {
10079 self.buf
10080 }
10081}
10082impl<'a> Iterator for IterableOpNapiGetDumpRequest<'a> {
10083 type Item = Result<OpNapiGetDumpRequest, ErrorContext>;
10084 fn next(&mut self) -> Option<Self::Item> {
10085 if self.buf.len() == self.pos {
10086 return None;
10087 }
10088 let pos = self.pos;
10089 let mut r#type = None;
10090 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10091 r#type = Some(header.r#type);
10092 let res = match header.r#type {
10093 1u16 => OpNapiGetDumpRequest::Ifindex({
10094 let res = parse_u32(next);
10095 let Some(val) = res else { break };
10096 val
10097 }),
10098 n => {
10099 if cfg!(any(test, feature = "deny-unknown-attrs")) {
10100 break;
10101 } else {
10102 continue;
10103 }
10104 }
10105 };
10106 return Some(Ok(res));
10107 }
10108 Some(Err(ErrorContext::new(
10109 "OpNapiGetDumpRequest",
10110 r#type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10111 self.orig_loc,
10112 self.buf.as_ptr().wrapping_add(pos) as usize,
10113 )))
10114 }
10115}
10116impl std::fmt::Debug for IterableOpNapiGetDumpRequest<'_> {
10117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10118 let mut fmt = f.debug_struct("OpNapiGetDumpRequest");
10119 for attr in self.clone() {
10120 let attr = match attr {
10121 Ok(a) => a,
10122 Err(err) => {
10123 fmt.finish()?;
10124 f.write_str("Err(")?;
10125 err.fmt(f)?;
10126 return f.write_str(")");
10127 }
10128 };
10129 match attr {
10130 OpNapiGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
10131 };
10132 }
10133 fmt.finish()
10134 }
10135}
10136impl IterableOpNapiGetDumpRequest<'_> {
10137 pub fn lookup_attr(
10138 &self,
10139 offset: usize,
10140 missing_type: Option<u16>,
10141 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10142 let mut stack = Vec::new();
10143 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10144 if cur == offset + PushBuiltinNfgenmsg::len() {
10145 stack.push(("OpNapiGetDumpRequest", offset));
10146 return (
10147 stack,
10148 missing_type.and_then(|t| OpNapiGetDumpRequest::attr_from_type(t)),
10149 );
10150 }
10151 if cur > offset || cur + self.buf.len() < offset {
10152 return (stack, None);
10153 }
10154 let mut attrs = self.clone();
10155 let mut last_off = cur + attrs.pos;
10156 while let Some(attr) = attrs.next() {
10157 let Ok(attr) = attr else { break };
10158 match attr {
10159 OpNapiGetDumpRequest::Ifindex(val) => {
10160 if last_off == offset {
10161 stack.push(("Ifindex", last_off));
10162 break;
10163 }
10164 }
10165 _ => {}
10166 };
10167 last_off = cur + attrs.pos;
10168 }
10169 if !stack.is_empty() {
10170 stack.push(("OpNapiGetDumpRequest", cur));
10171 }
10172 (stack, None)
10173 }
10174}
10175#[doc = "Get information about NAPI instances configured on the system."]
10176pub struct PushOpNapiGetDumpReply<Prev: Rec> {
10177 pub(crate) prev: Option<Prev>,
10178 pub(crate) header_offset: Option<usize>,
10179}
10180impl<Prev: Rec> Rec for PushOpNapiGetDumpReply<Prev> {
10181 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10182 self.prev.as_mut().unwrap().as_rec_mut()
10183 }
10184}
10185impl<Prev: Rec> PushOpNapiGetDumpReply<Prev> {
10186 pub fn new(mut prev: Prev) -> Self {
10187 Self::write_header(&mut prev);
10188 Self::new_without_header(prev)
10189 }
10190 fn new_without_header(prev: Prev) -> Self {
10191 Self {
10192 prev: Some(prev),
10193 header_offset: None,
10194 }
10195 }
10196 fn write_header(prev: &mut Prev) {
10197 let mut header = PushBuiltinNfgenmsg::new();
10198 header.set_cmd(11u8);
10199 header.set_version(1u8);
10200 prev.as_rec_mut().extend(header.as_slice());
10201 }
10202 pub fn end_nested(mut self) -> Prev {
10203 let mut prev = self.prev.take().unwrap();
10204 if let Some(header_offset) = &self.header_offset {
10205 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10206 }
10207 prev
10208 }
10209 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10210 pub fn push_ifindex(mut self, value: u32) -> Self {
10211 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10212 self.as_rec_mut().extend(value.to_ne_bytes());
10213 self
10214 }
10215 #[doc = "ID of the NAPI instance."]
10216 pub fn push_id(mut self, value: u32) -> Self {
10217 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10218 self.as_rec_mut().extend(value.to_ne_bytes());
10219 self
10220 }
10221 #[doc = "The associated interrupt vector number for the napi"]
10222 pub fn push_irq(mut self, value: u32) -> Self {
10223 push_header(self.as_rec_mut(), 3u16, 4 as u16);
10224 self.as_rec_mut().extend(value.to_ne_bytes());
10225 self
10226 }
10227 #[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."]
10228 pub fn push_pid(mut self, value: u32) -> Self {
10229 push_header(self.as_rec_mut(), 4u16, 4 as u16);
10230 self.as_rec_mut().extend(value.to_ne_bytes());
10231 self
10232 }
10233 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10234 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10235 push_header(self.as_rec_mut(), 5u16, 4 as u16);
10236 self.as_rec_mut().extend(value.to_ne_bytes());
10237 self
10238 }
10239 #[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."]
10240 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10241 push_header(self.as_rec_mut(), 6u16, 4 as u16);
10242 self.as_rec_mut().extend(value.to_ne_bytes());
10243 self
10244 }
10245 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10246 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10247 push_header(self.as_rec_mut(), 7u16, 4 as u16);
10248 self.as_rec_mut().extend(value.to_ne_bytes());
10249 self
10250 }
10251 #[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)"]
10252 pub fn push_threaded(mut self, value: u32) -> Self {
10253 push_header(self.as_rec_mut(), 8u16, 4 as u16);
10254 self.as_rec_mut().extend(value.to_ne_bytes());
10255 self
10256 }
10257}
10258impl<Prev: Rec> Drop for PushOpNapiGetDumpReply<Prev> {
10259 fn drop(&mut self) {
10260 if let Some(prev) = &mut self.prev {
10261 if let Some(header_offset) = &self.header_offset {
10262 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10263 }
10264 }
10265 }
10266}
10267#[doc = "Get information about NAPI instances configured on the system."]
10268#[derive(Clone)]
10269pub enum OpNapiGetDumpReply {
10270 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10271 Ifindex(u32),
10272 #[doc = "ID of the NAPI instance."]
10273 Id(u32),
10274 #[doc = "The associated interrupt vector number for the napi"]
10275 Irq(u32),
10276 #[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."]
10277 Pid(u32),
10278 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10279 DeferHardIrqs(u32),
10280 #[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."]
10281 GroFlushTimeout(u32),
10282 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10283 IrqSuspendTimeout(u32),
10284 #[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)"]
10285 Threaded(u32),
10286}
10287impl<'a> IterableOpNapiGetDumpReply<'a> {
10288 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10289 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10290 let mut iter = self.clone();
10291 iter.pos = 0;
10292 for attr in iter {
10293 if let OpNapiGetDumpReply::Ifindex(val) = attr? {
10294 return Ok(val);
10295 }
10296 }
10297 Err(ErrorContext::new_missing(
10298 "OpNapiGetDumpReply",
10299 "Ifindex",
10300 self.orig_loc,
10301 self.buf.as_ptr() as usize,
10302 ))
10303 }
10304 #[doc = "ID of the NAPI instance."]
10305 pub fn get_id(&self) -> Result<u32, ErrorContext> {
10306 let mut iter = self.clone();
10307 iter.pos = 0;
10308 for attr in iter {
10309 if let OpNapiGetDumpReply::Id(val) = attr? {
10310 return Ok(val);
10311 }
10312 }
10313 Err(ErrorContext::new_missing(
10314 "OpNapiGetDumpReply",
10315 "Id",
10316 self.orig_loc,
10317 self.buf.as_ptr() as usize,
10318 ))
10319 }
10320 #[doc = "The associated interrupt vector number for the napi"]
10321 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
10322 let mut iter = self.clone();
10323 iter.pos = 0;
10324 for attr in iter {
10325 if let OpNapiGetDumpReply::Irq(val) = attr? {
10326 return Ok(val);
10327 }
10328 }
10329 Err(ErrorContext::new_missing(
10330 "OpNapiGetDumpReply",
10331 "Irq",
10332 self.orig_loc,
10333 self.buf.as_ptr() as usize,
10334 ))
10335 }
10336 #[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."]
10337 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
10338 let mut iter = self.clone();
10339 iter.pos = 0;
10340 for attr in iter {
10341 if let OpNapiGetDumpReply::Pid(val) = attr? {
10342 return Ok(val);
10343 }
10344 }
10345 Err(ErrorContext::new_missing(
10346 "OpNapiGetDumpReply",
10347 "Pid",
10348 self.orig_loc,
10349 self.buf.as_ptr() as usize,
10350 ))
10351 }
10352 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10353 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
10354 let mut iter = self.clone();
10355 iter.pos = 0;
10356 for attr in iter {
10357 if let OpNapiGetDumpReply::DeferHardIrqs(val) = attr? {
10358 return Ok(val);
10359 }
10360 }
10361 Err(ErrorContext::new_missing(
10362 "OpNapiGetDumpReply",
10363 "DeferHardIrqs",
10364 self.orig_loc,
10365 self.buf.as_ptr() as usize,
10366 ))
10367 }
10368 #[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."]
10369 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
10370 let mut iter = self.clone();
10371 iter.pos = 0;
10372 for attr in iter {
10373 if let OpNapiGetDumpReply::GroFlushTimeout(val) = attr? {
10374 return Ok(val);
10375 }
10376 }
10377 Err(ErrorContext::new_missing(
10378 "OpNapiGetDumpReply",
10379 "GroFlushTimeout",
10380 self.orig_loc,
10381 self.buf.as_ptr() as usize,
10382 ))
10383 }
10384 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10385 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
10386 let mut iter = self.clone();
10387 iter.pos = 0;
10388 for attr in iter {
10389 if let OpNapiGetDumpReply::IrqSuspendTimeout(val) = attr? {
10390 return Ok(val);
10391 }
10392 }
10393 Err(ErrorContext::new_missing(
10394 "OpNapiGetDumpReply",
10395 "IrqSuspendTimeout",
10396 self.orig_loc,
10397 self.buf.as_ptr() as usize,
10398 ))
10399 }
10400 #[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)"]
10401 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
10402 let mut iter = self.clone();
10403 iter.pos = 0;
10404 for attr in iter {
10405 if let OpNapiGetDumpReply::Threaded(val) = attr? {
10406 return Ok(val);
10407 }
10408 }
10409 Err(ErrorContext::new_missing(
10410 "OpNapiGetDumpReply",
10411 "Threaded",
10412 self.orig_loc,
10413 self.buf.as_ptr() as usize,
10414 ))
10415 }
10416}
10417impl OpNapiGetDumpReply {
10418 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDumpReply<'a> {
10419 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10420 IterableOpNapiGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
10421 }
10422 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10423 Napi::attr_from_type(r#type)
10424 }
10425}
10426#[derive(Clone, Copy, Default)]
10427pub struct IterableOpNapiGetDumpReply<'a> {
10428 buf: &'a [u8],
10429 pos: usize,
10430 orig_loc: usize,
10431}
10432impl<'a> IterableOpNapiGetDumpReply<'a> {
10433 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10434 Self {
10435 buf,
10436 pos: 0,
10437 orig_loc,
10438 }
10439 }
10440 pub fn get_buf(&self) -> &'a [u8] {
10441 self.buf
10442 }
10443}
10444impl<'a> Iterator for IterableOpNapiGetDumpReply<'a> {
10445 type Item = Result<OpNapiGetDumpReply, ErrorContext>;
10446 fn next(&mut self) -> Option<Self::Item> {
10447 if self.buf.len() == self.pos {
10448 return None;
10449 }
10450 let pos = self.pos;
10451 let mut r#type = None;
10452 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10453 r#type = Some(header.r#type);
10454 let res = match header.r#type {
10455 1u16 => OpNapiGetDumpReply::Ifindex({
10456 let res = parse_u32(next);
10457 let Some(val) = res else { break };
10458 val
10459 }),
10460 2u16 => OpNapiGetDumpReply::Id({
10461 let res = parse_u32(next);
10462 let Some(val) = res else { break };
10463 val
10464 }),
10465 3u16 => OpNapiGetDumpReply::Irq({
10466 let res = parse_u32(next);
10467 let Some(val) = res else { break };
10468 val
10469 }),
10470 4u16 => OpNapiGetDumpReply::Pid({
10471 let res = parse_u32(next);
10472 let Some(val) = res else { break };
10473 val
10474 }),
10475 5u16 => OpNapiGetDumpReply::DeferHardIrqs({
10476 let res = parse_u32(next);
10477 let Some(val) = res else { break };
10478 val
10479 }),
10480 6u16 => OpNapiGetDumpReply::GroFlushTimeout({
10481 let res = parse_u32(next);
10482 let Some(val) = res else { break };
10483 val
10484 }),
10485 7u16 => OpNapiGetDumpReply::IrqSuspendTimeout({
10486 let res = parse_u32(next);
10487 let Some(val) = res else { break };
10488 val
10489 }),
10490 8u16 => OpNapiGetDumpReply::Threaded({
10491 let res = parse_u32(next);
10492 let Some(val) = res else { break };
10493 val
10494 }),
10495 n => {
10496 if cfg!(any(test, feature = "deny-unknown-attrs")) {
10497 break;
10498 } else {
10499 continue;
10500 }
10501 }
10502 };
10503 return Some(Ok(res));
10504 }
10505 Some(Err(ErrorContext::new(
10506 "OpNapiGetDumpReply",
10507 r#type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10508 self.orig_loc,
10509 self.buf.as_ptr().wrapping_add(pos) as usize,
10510 )))
10511 }
10512}
10513impl std::fmt::Debug for IterableOpNapiGetDumpReply<'_> {
10514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10515 let mut fmt = f.debug_struct("OpNapiGetDumpReply");
10516 for attr in self.clone() {
10517 let attr = match attr {
10518 Ok(a) => a,
10519 Err(err) => {
10520 fmt.finish()?;
10521 f.write_str("Err(")?;
10522 err.fmt(f)?;
10523 return f.write_str(")");
10524 }
10525 };
10526 match attr {
10527 OpNapiGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
10528 OpNapiGetDumpReply::Id(val) => fmt.field("Id", &val),
10529 OpNapiGetDumpReply::Irq(val) => fmt.field("Irq", &val),
10530 OpNapiGetDumpReply::Pid(val) => fmt.field("Pid", &val),
10531 OpNapiGetDumpReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
10532 OpNapiGetDumpReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
10533 OpNapiGetDumpReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
10534 OpNapiGetDumpReply::Threaded(val) => fmt.field(
10535 "Threaded",
10536 &FormatEnum(val.into(), NapiThreaded::from_value),
10537 ),
10538 };
10539 }
10540 fmt.finish()
10541 }
10542}
10543impl IterableOpNapiGetDumpReply<'_> {
10544 pub fn lookup_attr(
10545 &self,
10546 offset: usize,
10547 missing_type: Option<u16>,
10548 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10549 let mut stack = Vec::new();
10550 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10551 if cur == offset + PushBuiltinNfgenmsg::len() {
10552 stack.push(("OpNapiGetDumpReply", offset));
10553 return (
10554 stack,
10555 missing_type.and_then(|t| OpNapiGetDumpReply::attr_from_type(t)),
10556 );
10557 }
10558 if cur > offset || cur + self.buf.len() < offset {
10559 return (stack, None);
10560 }
10561 let mut attrs = self.clone();
10562 let mut last_off = cur + attrs.pos;
10563 while let Some(attr) = attrs.next() {
10564 let Ok(attr) = attr else { break };
10565 match attr {
10566 OpNapiGetDumpReply::Ifindex(val) => {
10567 if last_off == offset {
10568 stack.push(("Ifindex", last_off));
10569 break;
10570 }
10571 }
10572 OpNapiGetDumpReply::Id(val) => {
10573 if last_off == offset {
10574 stack.push(("Id", last_off));
10575 break;
10576 }
10577 }
10578 OpNapiGetDumpReply::Irq(val) => {
10579 if last_off == offset {
10580 stack.push(("Irq", last_off));
10581 break;
10582 }
10583 }
10584 OpNapiGetDumpReply::Pid(val) => {
10585 if last_off == offset {
10586 stack.push(("Pid", last_off));
10587 break;
10588 }
10589 }
10590 OpNapiGetDumpReply::DeferHardIrqs(val) => {
10591 if last_off == offset {
10592 stack.push(("DeferHardIrqs", last_off));
10593 break;
10594 }
10595 }
10596 OpNapiGetDumpReply::GroFlushTimeout(val) => {
10597 if last_off == offset {
10598 stack.push(("GroFlushTimeout", last_off));
10599 break;
10600 }
10601 }
10602 OpNapiGetDumpReply::IrqSuspendTimeout(val) => {
10603 if last_off == offset {
10604 stack.push(("IrqSuspendTimeout", last_off));
10605 break;
10606 }
10607 }
10608 OpNapiGetDumpReply::Threaded(val) => {
10609 if last_off == offset {
10610 stack.push(("Threaded", last_off));
10611 break;
10612 }
10613 }
10614 _ => {}
10615 };
10616 last_off = cur + attrs.pos;
10617 }
10618 if !stack.is_empty() {
10619 stack.push(("OpNapiGetDumpReply", cur));
10620 }
10621 (stack, None)
10622 }
10623}
10624#[derive(Debug)]
10625pub struct RequestOpNapiGetDumpRequest<'r> {
10626 request: Request<'r>,
10627}
10628impl<'r> RequestOpNapiGetDumpRequest<'r> {
10629 pub fn new(mut request: Request<'r>) -> Self {
10630 PushOpNapiGetDumpRequest::write_header(&mut request.buf_mut());
10631 Self {
10632 request: request.set_dump(),
10633 }
10634 }
10635 pub fn encode(&mut self) -> PushOpNapiGetDumpRequest<&mut Vec<u8>> {
10636 PushOpNapiGetDumpRequest::new_without_header(self.request.buf_mut())
10637 }
10638 pub fn into_encoder(self) -> PushOpNapiGetDumpRequest<RequestBuf<'r>> {
10639 PushOpNapiGetDumpRequest::new_without_header(self.request.buf)
10640 }
10641}
10642impl NetlinkRequest for RequestOpNapiGetDumpRequest<'_> {
10643 type ReplyType<'buf> = IterableOpNapiGetDumpReply<'buf>;
10644 fn protocol(&self) -> Protocol {
10645 Protocol::Generic("netdev".as_bytes())
10646 }
10647 fn flags(&self) -> u16 {
10648 self.request.flags
10649 }
10650 fn payload(&self) -> &[u8] {
10651 self.request.buf()
10652 }
10653 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
10654 OpNapiGetDumpReply::new(buf)
10655 }
10656 fn lookup(
10657 buf: &[u8],
10658 offset: usize,
10659 missing_type: Option<u16>,
10660 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10661 OpNapiGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
10662 }
10663}
10664#[doc = "Get information about NAPI instances configured on the system."]
10665pub struct PushOpNapiGetDoRequest<Prev: Rec> {
10666 pub(crate) prev: Option<Prev>,
10667 pub(crate) header_offset: Option<usize>,
10668}
10669impl<Prev: Rec> Rec for PushOpNapiGetDoRequest<Prev> {
10670 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10671 self.prev.as_mut().unwrap().as_rec_mut()
10672 }
10673}
10674impl<Prev: Rec> PushOpNapiGetDoRequest<Prev> {
10675 pub fn new(mut prev: Prev) -> Self {
10676 Self::write_header(&mut prev);
10677 Self::new_without_header(prev)
10678 }
10679 fn new_without_header(prev: Prev) -> Self {
10680 Self {
10681 prev: Some(prev),
10682 header_offset: None,
10683 }
10684 }
10685 fn write_header(prev: &mut Prev) {
10686 let mut header = PushBuiltinNfgenmsg::new();
10687 header.set_cmd(11u8);
10688 header.set_version(1u8);
10689 prev.as_rec_mut().extend(header.as_slice());
10690 }
10691 pub fn end_nested(mut self) -> Prev {
10692 let mut prev = self.prev.take().unwrap();
10693 if let Some(header_offset) = &self.header_offset {
10694 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10695 }
10696 prev
10697 }
10698 #[doc = "ID of the NAPI instance."]
10699 pub fn push_id(mut self, value: u32) -> Self {
10700 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10701 self.as_rec_mut().extend(value.to_ne_bytes());
10702 self
10703 }
10704}
10705impl<Prev: Rec> Drop for PushOpNapiGetDoRequest<Prev> {
10706 fn drop(&mut self) {
10707 if let Some(prev) = &mut self.prev {
10708 if let Some(header_offset) = &self.header_offset {
10709 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10710 }
10711 }
10712 }
10713}
10714#[doc = "Get information about NAPI instances configured on the system."]
10715#[derive(Clone)]
10716pub enum OpNapiGetDoRequest {
10717 #[doc = "ID of the NAPI instance."]
10718 Id(u32),
10719}
10720impl<'a> IterableOpNapiGetDoRequest<'a> {
10721 #[doc = "ID of the NAPI instance."]
10722 pub fn get_id(&self) -> Result<u32, ErrorContext> {
10723 let mut iter = self.clone();
10724 iter.pos = 0;
10725 for attr in iter {
10726 if let OpNapiGetDoRequest::Id(val) = attr? {
10727 return Ok(val);
10728 }
10729 }
10730 Err(ErrorContext::new_missing(
10731 "OpNapiGetDoRequest",
10732 "Id",
10733 self.orig_loc,
10734 self.buf.as_ptr() as usize,
10735 ))
10736 }
10737}
10738impl OpNapiGetDoRequest {
10739 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoRequest<'a> {
10740 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
10741 IterableOpNapiGetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
10742 }
10743 fn attr_from_type(r#type: u16) -> Option<&'static str> {
10744 Napi::attr_from_type(r#type)
10745 }
10746}
10747#[derive(Clone, Copy, Default)]
10748pub struct IterableOpNapiGetDoRequest<'a> {
10749 buf: &'a [u8],
10750 pos: usize,
10751 orig_loc: usize,
10752}
10753impl<'a> IterableOpNapiGetDoRequest<'a> {
10754 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
10755 Self {
10756 buf,
10757 pos: 0,
10758 orig_loc,
10759 }
10760 }
10761 pub fn get_buf(&self) -> &'a [u8] {
10762 self.buf
10763 }
10764}
10765impl<'a> Iterator for IterableOpNapiGetDoRequest<'a> {
10766 type Item = Result<OpNapiGetDoRequest, ErrorContext>;
10767 fn next(&mut self) -> Option<Self::Item> {
10768 if self.buf.len() == self.pos {
10769 return None;
10770 }
10771 let pos = self.pos;
10772 let mut r#type = None;
10773 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
10774 r#type = Some(header.r#type);
10775 let res = match header.r#type {
10776 2u16 => OpNapiGetDoRequest::Id({
10777 let res = parse_u32(next);
10778 let Some(val) = res else { break };
10779 val
10780 }),
10781 n => {
10782 if cfg!(any(test, feature = "deny-unknown-attrs")) {
10783 break;
10784 } else {
10785 continue;
10786 }
10787 }
10788 };
10789 return Some(Ok(res));
10790 }
10791 Some(Err(ErrorContext::new(
10792 "OpNapiGetDoRequest",
10793 r#type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10794 self.orig_loc,
10795 self.buf.as_ptr().wrapping_add(pos) as usize,
10796 )))
10797 }
10798}
10799impl std::fmt::Debug for IterableOpNapiGetDoRequest<'_> {
10800 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10801 let mut fmt = f.debug_struct("OpNapiGetDoRequest");
10802 for attr in self.clone() {
10803 let attr = match attr {
10804 Ok(a) => a,
10805 Err(err) => {
10806 fmt.finish()?;
10807 f.write_str("Err(")?;
10808 err.fmt(f)?;
10809 return f.write_str(")");
10810 }
10811 };
10812 match attr {
10813 OpNapiGetDoRequest::Id(val) => fmt.field("Id", &val),
10814 };
10815 }
10816 fmt.finish()
10817 }
10818}
10819impl IterableOpNapiGetDoRequest<'_> {
10820 pub fn lookup_attr(
10821 &self,
10822 offset: usize,
10823 missing_type: Option<u16>,
10824 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
10825 let mut stack = Vec::new();
10826 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
10827 if cur == offset + PushBuiltinNfgenmsg::len() {
10828 stack.push(("OpNapiGetDoRequest", offset));
10829 return (
10830 stack,
10831 missing_type.and_then(|t| OpNapiGetDoRequest::attr_from_type(t)),
10832 );
10833 }
10834 if cur > offset || cur + self.buf.len() < offset {
10835 return (stack, None);
10836 }
10837 let mut attrs = self.clone();
10838 let mut last_off = cur + attrs.pos;
10839 while let Some(attr) = attrs.next() {
10840 let Ok(attr) = attr else { break };
10841 match attr {
10842 OpNapiGetDoRequest::Id(val) => {
10843 if last_off == offset {
10844 stack.push(("Id", last_off));
10845 break;
10846 }
10847 }
10848 _ => {}
10849 };
10850 last_off = cur + attrs.pos;
10851 }
10852 if !stack.is_empty() {
10853 stack.push(("OpNapiGetDoRequest", cur));
10854 }
10855 (stack, None)
10856 }
10857}
10858#[doc = "Get information about NAPI instances configured on the system."]
10859pub struct PushOpNapiGetDoReply<Prev: Rec> {
10860 pub(crate) prev: Option<Prev>,
10861 pub(crate) header_offset: Option<usize>,
10862}
10863impl<Prev: Rec> Rec for PushOpNapiGetDoReply<Prev> {
10864 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
10865 self.prev.as_mut().unwrap().as_rec_mut()
10866 }
10867}
10868impl<Prev: Rec> PushOpNapiGetDoReply<Prev> {
10869 pub fn new(mut prev: Prev) -> Self {
10870 Self::write_header(&mut prev);
10871 Self::new_without_header(prev)
10872 }
10873 fn new_without_header(prev: Prev) -> Self {
10874 Self {
10875 prev: Some(prev),
10876 header_offset: None,
10877 }
10878 }
10879 fn write_header(prev: &mut Prev) {
10880 let mut header = PushBuiltinNfgenmsg::new();
10881 header.set_cmd(11u8);
10882 header.set_version(1u8);
10883 prev.as_rec_mut().extend(header.as_slice());
10884 }
10885 pub fn end_nested(mut self) -> Prev {
10886 let mut prev = self.prev.take().unwrap();
10887 if let Some(header_offset) = &self.header_offset {
10888 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10889 }
10890 prev
10891 }
10892 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10893 pub fn push_ifindex(mut self, value: u32) -> Self {
10894 push_header(self.as_rec_mut(), 1u16, 4 as u16);
10895 self.as_rec_mut().extend(value.to_ne_bytes());
10896 self
10897 }
10898 #[doc = "ID of the NAPI instance."]
10899 pub fn push_id(mut self, value: u32) -> Self {
10900 push_header(self.as_rec_mut(), 2u16, 4 as u16);
10901 self.as_rec_mut().extend(value.to_ne_bytes());
10902 self
10903 }
10904 #[doc = "The associated interrupt vector number for the napi"]
10905 pub fn push_irq(mut self, value: u32) -> Self {
10906 push_header(self.as_rec_mut(), 3u16, 4 as u16);
10907 self.as_rec_mut().extend(value.to_ne_bytes());
10908 self
10909 }
10910 #[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."]
10911 pub fn push_pid(mut self, value: u32) -> Self {
10912 push_header(self.as_rec_mut(), 4u16, 4 as u16);
10913 self.as_rec_mut().extend(value.to_ne_bytes());
10914 self
10915 }
10916 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10917 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
10918 push_header(self.as_rec_mut(), 5u16, 4 as u16);
10919 self.as_rec_mut().extend(value.to_ne_bytes());
10920 self
10921 }
10922 #[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."]
10923 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
10924 push_header(self.as_rec_mut(), 6u16, 4 as u16);
10925 self.as_rec_mut().extend(value.to_ne_bytes());
10926 self
10927 }
10928 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10929 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
10930 push_header(self.as_rec_mut(), 7u16, 4 as u16);
10931 self.as_rec_mut().extend(value.to_ne_bytes());
10932 self
10933 }
10934 #[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)"]
10935 pub fn push_threaded(mut self, value: u32) -> Self {
10936 push_header(self.as_rec_mut(), 8u16, 4 as u16);
10937 self.as_rec_mut().extend(value.to_ne_bytes());
10938 self
10939 }
10940}
10941impl<Prev: Rec> Drop for PushOpNapiGetDoReply<Prev> {
10942 fn drop(&mut self) {
10943 if let Some(prev) = &mut self.prev {
10944 if let Some(header_offset) = &self.header_offset {
10945 finalize_nested_header(prev.as_rec_mut(), *header_offset);
10946 }
10947 }
10948 }
10949}
10950#[doc = "Get information about NAPI instances configured on the system."]
10951#[derive(Clone)]
10952pub enum OpNapiGetDoReply {
10953 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10954 Ifindex(u32),
10955 #[doc = "ID of the NAPI instance."]
10956 Id(u32),
10957 #[doc = "The associated interrupt vector number for the napi"]
10958 Irq(u32),
10959 #[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."]
10960 Pid(u32),
10961 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
10962 DeferHardIrqs(u32),
10963 #[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."]
10964 GroFlushTimeout(u32),
10965 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
10966 IrqSuspendTimeout(u32),
10967 #[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)"]
10968 Threaded(u32),
10969}
10970impl<'a> IterableOpNapiGetDoReply<'a> {
10971 #[doc = "ifindex of the netdevice to which NAPI instance belongs."]
10972 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
10973 let mut iter = self.clone();
10974 iter.pos = 0;
10975 for attr in iter {
10976 if let OpNapiGetDoReply::Ifindex(val) = attr? {
10977 return Ok(val);
10978 }
10979 }
10980 Err(ErrorContext::new_missing(
10981 "OpNapiGetDoReply",
10982 "Ifindex",
10983 self.orig_loc,
10984 self.buf.as_ptr() as usize,
10985 ))
10986 }
10987 #[doc = "ID of the NAPI instance."]
10988 pub fn get_id(&self) -> Result<u32, ErrorContext> {
10989 let mut iter = self.clone();
10990 iter.pos = 0;
10991 for attr in iter {
10992 if let OpNapiGetDoReply::Id(val) = attr? {
10993 return Ok(val);
10994 }
10995 }
10996 Err(ErrorContext::new_missing(
10997 "OpNapiGetDoReply",
10998 "Id",
10999 self.orig_loc,
11000 self.buf.as_ptr() as usize,
11001 ))
11002 }
11003 #[doc = "The associated interrupt vector number for the napi"]
11004 pub fn get_irq(&self) -> Result<u32, ErrorContext> {
11005 let mut iter = self.clone();
11006 iter.pos = 0;
11007 for attr in iter {
11008 if let OpNapiGetDoReply::Irq(val) = attr? {
11009 return Ok(val);
11010 }
11011 }
11012 Err(ErrorContext::new_missing(
11013 "OpNapiGetDoReply",
11014 "Irq",
11015 self.orig_loc,
11016 self.buf.as_ptr() as usize,
11017 ))
11018 }
11019 #[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."]
11020 pub fn get_pid(&self) -> Result<u32, ErrorContext> {
11021 let mut iter = self.clone();
11022 iter.pos = 0;
11023 for attr in iter {
11024 if let OpNapiGetDoReply::Pid(val) = attr? {
11025 return Ok(val);
11026 }
11027 }
11028 Err(ErrorContext::new_missing(
11029 "OpNapiGetDoReply",
11030 "Pid",
11031 self.orig_loc,
11032 self.buf.as_ptr() as usize,
11033 ))
11034 }
11035 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
11036 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
11037 let mut iter = self.clone();
11038 iter.pos = 0;
11039 for attr in iter {
11040 if let OpNapiGetDoReply::DeferHardIrqs(val) = attr? {
11041 return Ok(val);
11042 }
11043 }
11044 Err(ErrorContext::new_missing(
11045 "OpNapiGetDoReply",
11046 "DeferHardIrqs",
11047 self.orig_loc,
11048 self.buf.as_ptr() as usize,
11049 ))
11050 }
11051 #[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."]
11052 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
11053 let mut iter = self.clone();
11054 iter.pos = 0;
11055 for attr in iter {
11056 if let OpNapiGetDoReply::GroFlushTimeout(val) = attr? {
11057 return Ok(val);
11058 }
11059 }
11060 Err(ErrorContext::new_missing(
11061 "OpNapiGetDoReply",
11062 "GroFlushTimeout",
11063 self.orig_loc,
11064 self.buf.as_ptr() as usize,
11065 ))
11066 }
11067 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
11068 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
11069 let mut iter = self.clone();
11070 iter.pos = 0;
11071 for attr in iter {
11072 if let OpNapiGetDoReply::IrqSuspendTimeout(val) = attr? {
11073 return Ok(val);
11074 }
11075 }
11076 Err(ErrorContext::new_missing(
11077 "OpNapiGetDoReply",
11078 "IrqSuspendTimeout",
11079 self.orig_loc,
11080 self.buf.as_ptr() as usize,
11081 ))
11082 }
11083 #[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)"]
11084 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
11085 let mut iter = self.clone();
11086 iter.pos = 0;
11087 for attr in iter {
11088 if let OpNapiGetDoReply::Threaded(val) = attr? {
11089 return Ok(val);
11090 }
11091 }
11092 Err(ErrorContext::new_missing(
11093 "OpNapiGetDoReply",
11094 "Threaded",
11095 self.orig_loc,
11096 self.buf.as_ptr() as usize,
11097 ))
11098 }
11099}
11100impl OpNapiGetDoReply {
11101 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiGetDoReply<'a> {
11102 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11103 IterableOpNapiGetDoReply::with_loc(attrs, buf.as_ptr() as usize)
11104 }
11105 fn attr_from_type(r#type: u16) -> Option<&'static str> {
11106 Napi::attr_from_type(r#type)
11107 }
11108}
11109#[derive(Clone, Copy, Default)]
11110pub struct IterableOpNapiGetDoReply<'a> {
11111 buf: &'a [u8],
11112 pos: usize,
11113 orig_loc: usize,
11114}
11115impl<'a> IterableOpNapiGetDoReply<'a> {
11116 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11117 Self {
11118 buf,
11119 pos: 0,
11120 orig_loc,
11121 }
11122 }
11123 pub fn get_buf(&self) -> &'a [u8] {
11124 self.buf
11125 }
11126}
11127impl<'a> Iterator for IterableOpNapiGetDoReply<'a> {
11128 type Item = Result<OpNapiGetDoReply, ErrorContext>;
11129 fn next(&mut self) -> Option<Self::Item> {
11130 if self.buf.len() == self.pos {
11131 return None;
11132 }
11133 let pos = self.pos;
11134 let mut r#type = None;
11135 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
11136 r#type = Some(header.r#type);
11137 let res = match header.r#type {
11138 1u16 => OpNapiGetDoReply::Ifindex({
11139 let res = parse_u32(next);
11140 let Some(val) = res else { break };
11141 val
11142 }),
11143 2u16 => OpNapiGetDoReply::Id({
11144 let res = parse_u32(next);
11145 let Some(val) = res else { break };
11146 val
11147 }),
11148 3u16 => OpNapiGetDoReply::Irq({
11149 let res = parse_u32(next);
11150 let Some(val) = res else { break };
11151 val
11152 }),
11153 4u16 => OpNapiGetDoReply::Pid({
11154 let res = parse_u32(next);
11155 let Some(val) = res else { break };
11156 val
11157 }),
11158 5u16 => OpNapiGetDoReply::DeferHardIrqs({
11159 let res = parse_u32(next);
11160 let Some(val) = res else { break };
11161 val
11162 }),
11163 6u16 => OpNapiGetDoReply::GroFlushTimeout({
11164 let res = parse_u32(next);
11165 let Some(val) = res else { break };
11166 val
11167 }),
11168 7u16 => OpNapiGetDoReply::IrqSuspendTimeout({
11169 let res = parse_u32(next);
11170 let Some(val) = res else { break };
11171 val
11172 }),
11173 8u16 => OpNapiGetDoReply::Threaded({
11174 let res = parse_u32(next);
11175 let Some(val) = res else { break };
11176 val
11177 }),
11178 n => {
11179 if cfg!(any(test, feature = "deny-unknown-attrs")) {
11180 break;
11181 } else {
11182 continue;
11183 }
11184 }
11185 };
11186 return Some(Ok(res));
11187 }
11188 Some(Err(ErrorContext::new(
11189 "OpNapiGetDoReply",
11190 r#type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11191 self.orig_loc,
11192 self.buf.as_ptr().wrapping_add(pos) as usize,
11193 )))
11194 }
11195}
11196impl std::fmt::Debug for IterableOpNapiGetDoReply<'_> {
11197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11198 let mut fmt = f.debug_struct("OpNapiGetDoReply");
11199 for attr in self.clone() {
11200 let attr = match attr {
11201 Ok(a) => a,
11202 Err(err) => {
11203 fmt.finish()?;
11204 f.write_str("Err(")?;
11205 err.fmt(f)?;
11206 return f.write_str(")");
11207 }
11208 };
11209 match attr {
11210 OpNapiGetDoReply::Ifindex(val) => fmt.field("Ifindex", &val),
11211 OpNapiGetDoReply::Id(val) => fmt.field("Id", &val),
11212 OpNapiGetDoReply::Irq(val) => fmt.field("Irq", &val),
11213 OpNapiGetDoReply::Pid(val) => fmt.field("Pid", &val),
11214 OpNapiGetDoReply::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
11215 OpNapiGetDoReply::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
11216 OpNapiGetDoReply::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
11217 OpNapiGetDoReply::Threaded(val) => fmt.field(
11218 "Threaded",
11219 &FormatEnum(val.into(), NapiThreaded::from_value),
11220 ),
11221 };
11222 }
11223 fmt.finish()
11224 }
11225}
11226impl IterableOpNapiGetDoReply<'_> {
11227 pub fn lookup_attr(
11228 &self,
11229 offset: usize,
11230 missing_type: Option<u16>,
11231 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11232 let mut stack = Vec::new();
11233 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11234 if cur == offset + PushBuiltinNfgenmsg::len() {
11235 stack.push(("OpNapiGetDoReply", offset));
11236 return (
11237 stack,
11238 missing_type.and_then(|t| OpNapiGetDoReply::attr_from_type(t)),
11239 );
11240 }
11241 if cur > offset || cur + self.buf.len() < offset {
11242 return (stack, None);
11243 }
11244 let mut attrs = self.clone();
11245 let mut last_off = cur + attrs.pos;
11246 while let Some(attr) = attrs.next() {
11247 let Ok(attr) = attr else { break };
11248 match attr {
11249 OpNapiGetDoReply::Ifindex(val) => {
11250 if last_off == offset {
11251 stack.push(("Ifindex", last_off));
11252 break;
11253 }
11254 }
11255 OpNapiGetDoReply::Id(val) => {
11256 if last_off == offset {
11257 stack.push(("Id", last_off));
11258 break;
11259 }
11260 }
11261 OpNapiGetDoReply::Irq(val) => {
11262 if last_off == offset {
11263 stack.push(("Irq", last_off));
11264 break;
11265 }
11266 }
11267 OpNapiGetDoReply::Pid(val) => {
11268 if last_off == offset {
11269 stack.push(("Pid", last_off));
11270 break;
11271 }
11272 }
11273 OpNapiGetDoReply::DeferHardIrqs(val) => {
11274 if last_off == offset {
11275 stack.push(("DeferHardIrqs", last_off));
11276 break;
11277 }
11278 }
11279 OpNapiGetDoReply::GroFlushTimeout(val) => {
11280 if last_off == offset {
11281 stack.push(("GroFlushTimeout", last_off));
11282 break;
11283 }
11284 }
11285 OpNapiGetDoReply::IrqSuspendTimeout(val) => {
11286 if last_off == offset {
11287 stack.push(("IrqSuspendTimeout", last_off));
11288 break;
11289 }
11290 }
11291 OpNapiGetDoReply::Threaded(val) => {
11292 if last_off == offset {
11293 stack.push(("Threaded", last_off));
11294 break;
11295 }
11296 }
11297 _ => {}
11298 };
11299 last_off = cur + attrs.pos;
11300 }
11301 if !stack.is_empty() {
11302 stack.push(("OpNapiGetDoReply", cur));
11303 }
11304 (stack, None)
11305 }
11306}
11307#[derive(Debug)]
11308pub struct RequestOpNapiGetDoRequest<'r> {
11309 request: Request<'r>,
11310}
11311impl<'r> RequestOpNapiGetDoRequest<'r> {
11312 pub fn new(mut request: Request<'r>) -> Self {
11313 PushOpNapiGetDoRequest::write_header(&mut request.buf_mut());
11314 Self { request: request }
11315 }
11316 pub fn encode(&mut self) -> PushOpNapiGetDoRequest<&mut Vec<u8>> {
11317 PushOpNapiGetDoRequest::new_without_header(self.request.buf_mut())
11318 }
11319 pub fn into_encoder(self) -> PushOpNapiGetDoRequest<RequestBuf<'r>> {
11320 PushOpNapiGetDoRequest::new_without_header(self.request.buf)
11321 }
11322}
11323impl NetlinkRequest for RequestOpNapiGetDoRequest<'_> {
11324 type ReplyType<'buf> = IterableOpNapiGetDoReply<'buf>;
11325 fn protocol(&self) -> Protocol {
11326 Protocol::Generic("netdev".as_bytes())
11327 }
11328 fn flags(&self) -> u16 {
11329 self.request.flags
11330 }
11331 fn payload(&self) -> &[u8] {
11332 self.request.buf()
11333 }
11334 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
11335 OpNapiGetDoReply::new(buf)
11336 }
11337 fn lookup(
11338 buf: &[u8],
11339 offset: usize,
11340 missing_type: Option<u16>,
11341 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11342 OpNapiGetDoRequest::new(buf).lookup_attr(offset, missing_type)
11343 }
11344}
11345#[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"]
11346pub struct PushOpQstatsGetDumpRequest<Prev: Rec> {
11347 pub(crate) prev: Option<Prev>,
11348 pub(crate) header_offset: Option<usize>,
11349}
11350impl<Prev: Rec> Rec for PushOpQstatsGetDumpRequest<Prev> {
11351 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11352 self.prev.as_mut().unwrap().as_rec_mut()
11353 }
11354}
11355impl<Prev: Rec> PushOpQstatsGetDumpRequest<Prev> {
11356 pub fn new(mut prev: Prev) -> Self {
11357 Self::write_header(&mut prev);
11358 Self::new_without_header(prev)
11359 }
11360 fn new_without_header(prev: Prev) -> Self {
11361 Self {
11362 prev: Some(prev),
11363 header_offset: None,
11364 }
11365 }
11366 fn write_header(prev: &mut Prev) {
11367 let mut header = PushBuiltinNfgenmsg::new();
11368 header.set_cmd(12u8);
11369 header.set_version(1u8);
11370 prev.as_rec_mut().extend(header.as_slice());
11371 }
11372 pub fn end_nested(mut self) -> Prev {
11373 let mut prev = self.prev.take().unwrap();
11374 if let Some(header_offset) = &self.header_offset {
11375 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11376 }
11377 prev
11378 }
11379 #[doc = "ifindex of the netdevice to which stats belong."]
11380 pub fn push_ifindex(mut self, value: u32) -> Self {
11381 push_header(self.as_rec_mut(), 1u16, 4 as u16);
11382 self.as_rec_mut().extend(value.to_ne_bytes());
11383 self
11384 }
11385 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11386 pub fn push_scope(mut self, value: u32) -> Self {
11387 push_header(self.as_rec_mut(), 4u16, 4 as u16);
11388 self.as_rec_mut().extend(value.to_ne_bytes());
11389 self
11390 }
11391}
11392impl<Prev: Rec> Drop for PushOpQstatsGetDumpRequest<Prev> {
11393 fn drop(&mut self) {
11394 if let Some(prev) = &mut self.prev {
11395 if let Some(header_offset) = &self.header_offset {
11396 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11397 }
11398 }
11399 }
11400}
11401#[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"]
11402#[derive(Clone)]
11403pub enum OpQstatsGetDumpRequest {
11404 #[doc = "ifindex of the netdevice to which stats belong."]
11405 Ifindex(u32),
11406 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11407 Scope(u32),
11408}
11409impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11410 #[doc = "ifindex of the netdevice to which stats belong."]
11411 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11412 let mut iter = self.clone();
11413 iter.pos = 0;
11414 for attr in iter {
11415 if let OpQstatsGetDumpRequest::Ifindex(val) = attr? {
11416 return Ok(val);
11417 }
11418 }
11419 Err(ErrorContext::new_missing(
11420 "OpQstatsGetDumpRequest",
11421 "Ifindex",
11422 self.orig_loc,
11423 self.buf.as_ptr() as usize,
11424 ))
11425 }
11426 #[doc = "What object type should be used to iterate over the stats.\n\nAssociated type: \"QstatsScope\" (enum)"]
11427 pub fn get_scope(&self) -> Result<u32, ErrorContext> {
11428 let mut iter = self.clone();
11429 iter.pos = 0;
11430 for attr in iter {
11431 if let OpQstatsGetDumpRequest::Scope(val) = attr? {
11432 return Ok(val);
11433 }
11434 }
11435 Err(ErrorContext::new_missing(
11436 "OpQstatsGetDumpRequest",
11437 "Scope",
11438 self.orig_loc,
11439 self.buf.as_ptr() as usize,
11440 ))
11441 }
11442}
11443impl OpQstatsGetDumpRequest {
11444 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpRequest<'a> {
11445 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
11446 IterableOpQstatsGetDumpRequest::with_loc(attrs, buf.as_ptr() as usize)
11447 }
11448 fn attr_from_type(r#type: u16) -> Option<&'static str> {
11449 Qstats::attr_from_type(r#type)
11450 }
11451}
11452#[derive(Clone, Copy, Default)]
11453pub struct IterableOpQstatsGetDumpRequest<'a> {
11454 buf: &'a [u8],
11455 pos: usize,
11456 orig_loc: usize,
11457}
11458impl<'a> IterableOpQstatsGetDumpRequest<'a> {
11459 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
11460 Self {
11461 buf,
11462 pos: 0,
11463 orig_loc,
11464 }
11465 }
11466 pub fn get_buf(&self) -> &'a [u8] {
11467 self.buf
11468 }
11469}
11470impl<'a> Iterator for IterableOpQstatsGetDumpRequest<'a> {
11471 type Item = Result<OpQstatsGetDumpRequest, ErrorContext>;
11472 fn next(&mut self) -> Option<Self::Item> {
11473 if self.buf.len() == self.pos {
11474 return None;
11475 }
11476 let pos = self.pos;
11477 let mut r#type = None;
11478 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
11479 r#type = Some(header.r#type);
11480 let res = match header.r#type {
11481 1u16 => OpQstatsGetDumpRequest::Ifindex({
11482 let res = parse_u32(next);
11483 let Some(val) = res else { break };
11484 val
11485 }),
11486 4u16 => OpQstatsGetDumpRequest::Scope({
11487 let res = parse_u32(next);
11488 let Some(val) = res else { break };
11489 val
11490 }),
11491 n => {
11492 if cfg!(any(test, feature = "deny-unknown-attrs")) {
11493 break;
11494 } else {
11495 continue;
11496 }
11497 }
11498 };
11499 return Some(Ok(res));
11500 }
11501 Some(Err(ErrorContext::new(
11502 "OpQstatsGetDumpRequest",
11503 r#type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11504 self.orig_loc,
11505 self.buf.as_ptr().wrapping_add(pos) as usize,
11506 )))
11507 }
11508}
11509impl std::fmt::Debug for IterableOpQstatsGetDumpRequest<'_> {
11510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11511 let mut fmt = f.debug_struct("OpQstatsGetDumpRequest");
11512 for attr in self.clone() {
11513 let attr = match attr {
11514 Ok(a) => a,
11515 Err(err) => {
11516 fmt.finish()?;
11517 f.write_str("Err(")?;
11518 err.fmt(f)?;
11519 return f.write_str(")");
11520 }
11521 };
11522 match attr {
11523 OpQstatsGetDumpRequest::Ifindex(val) => fmt.field("Ifindex", &val),
11524 OpQstatsGetDumpRequest::Scope(val) => {
11525 fmt.field("Scope", &FormatFlags(val.into(), QstatsScope::from_value))
11526 }
11527 };
11528 }
11529 fmt.finish()
11530 }
11531}
11532impl IterableOpQstatsGetDumpRequest<'_> {
11533 pub fn lookup_attr(
11534 &self,
11535 offset: usize,
11536 missing_type: Option<u16>,
11537 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
11538 let mut stack = Vec::new();
11539 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
11540 if cur == offset + PushBuiltinNfgenmsg::len() {
11541 stack.push(("OpQstatsGetDumpRequest", offset));
11542 return (
11543 stack,
11544 missing_type.and_then(|t| OpQstatsGetDumpRequest::attr_from_type(t)),
11545 );
11546 }
11547 if cur > offset || cur + self.buf.len() < offset {
11548 return (stack, None);
11549 }
11550 let mut attrs = self.clone();
11551 let mut last_off = cur + attrs.pos;
11552 while let Some(attr) = attrs.next() {
11553 let Ok(attr) = attr else { break };
11554 match attr {
11555 OpQstatsGetDumpRequest::Ifindex(val) => {
11556 if last_off == offset {
11557 stack.push(("Ifindex", last_off));
11558 break;
11559 }
11560 }
11561 OpQstatsGetDumpRequest::Scope(val) => {
11562 if last_off == offset {
11563 stack.push(("Scope", last_off));
11564 break;
11565 }
11566 }
11567 _ => {}
11568 };
11569 last_off = cur + attrs.pos;
11570 }
11571 if !stack.is_empty() {
11572 stack.push(("OpQstatsGetDumpRequest", cur));
11573 }
11574 (stack, None)
11575 }
11576}
11577#[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"]
11578pub struct PushOpQstatsGetDumpReply<Prev: Rec> {
11579 pub(crate) prev: Option<Prev>,
11580 pub(crate) header_offset: Option<usize>,
11581}
11582impl<Prev: Rec> Rec for PushOpQstatsGetDumpReply<Prev> {
11583 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
11584 self.prev.as_mut().unwrap().as_rec_mut()
11585 }
11586}
11587impl<Prev: Rec> PushOpQstatsGetDumpReply<Prev> {
11588 pub fn new(mut prev: Prev) -> Self {
11589 Self::write_header(&mut prev);
11590 Self::new_without_header(prev)
11591 }
11592 fn new_without_header(prev: Prev) -> Self {
11593 Self {
11594 prev: Some(prev),
11595 header_offset: None,
11596 }
11597 }
11598 fn write_header(prev: &mut Prev) {
11599 let mut header = PushBuiltinNfgenmsg::new();
11600 header.set_cmd(12u8);
11601 header.set_version(1u8);
11602 prev.as_rec_mut().extend(header.as_slice());
11603 }
11604 pub fn end_nested(mut self) -> Prev {
11605 let mut prev = self.prev.take().unwrap();
11606 if let Some(header_offset) = &self.header_offset {
11607 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11608 }
11609 prev
11610 }
11611 #[doc = "ifindex of the netdevice to which stats belong."]
11612 pub fn push_ifindex(mut self, value: u32) -> Self {
11613 push_header(self.as_rec_mut(), 1u16, 4 as u16);
11614 self.as_rec_mut().extend(value.to_ne_bytes());
11615 self
11616 }
11617 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11618 pub fn push_queue_type(mut self, value: u32) -> Self {
11619 push_header(self.as_rec_mut(), 2u16, 4 as u16);
11620 self.as_rec_mut().extend(value.to_ne_bytes());
11621 self
11622 }
11623 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11624 pub fn push_queue_id(mut self, value: u32) -> Self {
11625 push_header(self.as_rec_mut(), 3u16, 4 as u16);
11626 self.as_rec_mut().extend(value.to_ne_bytes());
11627 self
11628 }
11629 #[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"]
11630 pub fn push_rx_packets(mut self, value: u32) -> Self {
11631 push_header(self.as_rec_mut(), 8u16, 4 as u16);
11632 self.as_rec_mut().extend(value.to_ne_bytes());
11633 self
11634 }
11635 #[doc = "Successfully received bytes, see `rx-packets`."]
11636 pub fn push_rx_bytes(mut self, value: u32) -> Self {
11637 push_header(self.as_rec_mut(), 9u16, 4 as u16);
11638 self.as_rec_mut().extend(value.to_ne_bytes());
11639 self
11640 }
11641 #[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"]
11642 pub fn push_tx_packets(mut self, value: u32) -> Self {
11643 push_header(self.as_rec_mut(), 10u16, 4 as u16);
11644 self.as_rec_mut().extend(value.to_ne_bytes());
11645 self
11646 }
11647 #[doc = "Successfully sent bytes, see `tx-packets`."]
11648 pub fn push_tx_bytes(mut self, value: u32) -> Self {
11649 push_header(self.as_rec_mut(), 11u16, 4 as u16);
11650 self.as_rec_mut().extend(value.to_ne_bytes());
11651 self
11652 }
11653 #[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"]
11654 pub fn push_rx_alloc_fail(mut self, value: u32) -> Self {
11655 push_header(self.as_rec_mut(), 12u16, 4 as u16);
11656 self.as_rec_mut().extend(value.to_ne_bytes());
11657 self
11658 }
11659 #[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"]
11660 pub fn push_rx_hw_drops(mut self, value: u32) -> Self {
11661 push_header(self.as_rec_mut(), 13u16, 4 as u16);
11662 self.as_rec_mut().extend(value.to_ne_bytes());
11663 self
11664 }
11665 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11666 pub fn push_rx_hw_drop_overruns(mut self, value: u32) -> Self {
11667 push_header(self.as_rec_mut(), 14u16, 4 as u16);
11668 self.as_rec_mut().extend(value.to_ne_bytes());
11669 self
11670 }
11671 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11672 pub fn push_rx_csum_complete(mut self, value: u32) -> Self {
11673 push_header(self.as_rec_mut(), 15u16, 4 as u16);
11674 self.as_rec_mut().extend(value.to_ne_bytes());
11675 self
11676 }
11677 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11678 pub fn push_rx_csum_unnecessary(mut self, value: u32) -> Self {
11679 push_header(self.as_rec_mut(), 16u16, 4 as u16);
11680 self.as_rec_mut().extend(value.to_ne_bytes());
11681 self
11682 }
11683 #[doc = "Number of packets that were not checksummed by device."]
11684 pub fn push_rx_csum_none(mut self, value: u32) -> Self {
11685 push_header(self.as_rec_mut(), 17u16, 4 as u16);
11686 self.as_rec_mut().extend(value.to_ne_bytes());
11687 self
11688 }
11689 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11690 pub fn push_rx_csum_bad(mut self, value: u32) -> Self {
11691 push_header(self.as_rec_mut(), 18u16, 4 as u16);
11692 self.as_rec_mut().extend(value.to_ne_bytes());
11693 self
11694 }
11695 #[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"]
11696 pub fn push_rx_hw_gro_packets(mut self, value: u32) -> Self {
11697 push_header(self.as_rec_mut(), 19u16, 4 as u16);
11698 self.as_rec_mut().extend(value.to_ne_bytes());
11699 self
11700 }
11701 #[doc = "See `rx-hw-gro-packets`."]
11702 pub fn push_rx_hw_gro_bytes(mut self, value: u32) -> Self {
11703 push_header(self.as_rec_mut(), 20u16, 4 as u16);
11704 self.as_rec_mut().extend(value.to_ne_bytes());
11705 self
11706 }
11707 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11708 pub fn push_rx_hw_gro_wire_packets(mut self, value: u32) -> Self {
11709 push_header(self.as_rec_mut(), 21u16, 4 as u16);
11710 self.as_rec_mut().extend(value.to_ne_bytes());
11711 self
11712 }
11713 #[doc = "See `rx-hw-gro-wire-packets`."]
11714 pub fn push_rx_hw_gro_wire_bytes(mut self, value: u32) -> Self {
11715 push_header(self.as_rec_mut(), 22u16, 4 as u16);
11716 self.as_rec_mut().extend(value.to_ne_bytes());
11717 self
11718 }
11719 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11720 pub fn push_rx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11721 push_header(self.as_rec_mut(), 23u16, 4 as u16);
11722 self.as_rec_mut().extend(value.to_ne_bytes());
11723 self
11724 }
11725 #[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"]
11726 pub fn push_tx_hw_drops(mut self, value: u32) -> Self {
11727 push_header(self.as_rec_mut(), 24u16, 4 as u16);
11728 self.as_rec_mut().extend(value.to_ne_bytes());
11729 self
11730 }
11731 #[doc = "Number of packets dropped because they were invalid or malformed."]
11732 pub fn push_tx_hw_drop_errors(mut self, value: u32) -> Self {
11733 push_header(self.as_rec_mut(), 25u16, 4 as u16);
11734 self.as_rec_mut().extend(value.to_ne_bytes());
11735 self
11736 }
11737 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11738 pub fn push_tx_csum_none(mut self, value: u32) -> Self {
11739 push_header(self.as_rec_mut(), 26u16, 4 as u16);
11740 self.as_rec_mut().extend(value.to_ne_bytes());
11741 self
11742 }
11743 #[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"]
11744 pub fn push_tx_needs_csum(mut self, value: u32) -> Self {
11745 push_header(self.as_rec_mut(), 27u16, 4 as u16);
11746 self.as_rec_mut().extend(value.to_ne_bytes());
11747 self
11748 }
11749 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11750 pub fn push_tx_hw_gso_packets(mut self, value: u32) -> Self {
11751 push_header(self.as_rec_mut(), 28u16, 4 as u16);
11752 self.as_rec_mut().extend(value.to_ne_bytes());
11753 self
11754 }
11755 #[doc = "See `tx-hw-gso-packets`."]
11756 pub fn push_tx_hw_gso_bytes(mut self, value: u32) -> Self {
11757 push_header(self.as_rec_mut(), 29u16, 4 as u16);
11758 self.as_rec_mut().extend(value.to_ne_bytes());
11759 self
11760 }
11761 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11762 pub fn push_tx_hw_gso_wire_packets(mut self, value: u32) -> Self {
11763 push_header(self.as_rec_mut(), 30u16, 4 as u16);
11764 self.as_rec_mut().extend(value.to_ne_bytes());
11765 self
11766 }
11767 #[doc = "See `tx-hw-gso-wire-packets`."]
11768 pub fn push_tx_hw_gso_wire_bytes(mut self, value: u32) -> Self {
11769 push_header(self.as_rec_mut(), 31u16, 4 as u16);
11770 self.as_rec_mut().extend(value.to_ne_bytes());
11771 self
11772 }
11773 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11774 pub fn push_tx_hw_drop_ratelimits(mut self, value: u32) -> Self {
11775 push_header(self.as_rec_mut(), 32u16, 4 as u16);
11776 self.as_rec_mut().extend(value.to_ne_bytes());
11777 self
11778 }
11779 #[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"]
11780 pub fn push_tx_stop(mut self, value: u32) -> Self {
11781 push_header(self.as_rec_mut(), 33u16, 4 as u16);
11782 self.as_rec_mut().extend(value.to_ne_bytes());
11783 self
11784 }
11785 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11786 pub fn push_tx_wake(mut self, value: u32) -> Self {
11787 push_header(self.as_rec_mut(), 34u16, 4 as u16);
11788 self.as_rec_mut().extend(value.to_ne_bytes());
11789 self
11790 }
11791}
11792impl<Prev: Rec> Drop for PushOpQstatsGetDumpReply<Prev> {
11793 fn drop(&mut self) {
11794 if let Some(prev) = &mut self.prev {
11795 if let Some(header_offset) = &self.header_offset {
11796 finalize_nested_header(prev.as_rec_mut(), *header_offset);
11797 }
11798 }
11799 }
11800}
11801#[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"]
11802#[derive(Clone)]
11803pub enum OpQstatsGetDumpReply {
11804 #[doc = "ifindex of the netdevice to which stats belong."]
11805 Ifindex(u32),
11806 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11807 QueueType(u32),
11808 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11809 QueueId(u32),
11810 #[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"]
11811 RxPackets(u32),
11812 #[doc = "Successfully received bytes, see `rx-packets`."]
11813 RxBytes(u32),
11814 #[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"]
11815 TxPackets(u32),
11816 #[doc = "Successfully sent bytes, see `tx-packets`."]
11817 TxBytes(u32),
11818 #[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"]
11819 RxAllocFail(u32),
11820 #[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"]
11821 RxHwDrops(u32),
11822 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
11823 RxHwDropOverruns(u32),
11824 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
11825 RxCsumComplete(u32),
11826 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
11827 RxCsumUnnecessary(u32),
11828 #[doc = "Number of packets that were not checksummed by device."]
11829 RxCsumNone(u32),
11830 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
11831 RxCsumBad(u32),
11832 #[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"]
11833 RxHwGroPackets(u32),
11834 #[doc = "See `rx-hw-gro-packets`."]
11835 RxHwGroBytes(u32),
11836 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
11837 RxHwGroWirePackets(u32),
11838 #[doc = "See `rx-hw-gro-wire-packets`."]
11839 RxHwGroWireBytes(u32),
11840 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
11841 RxHwDropRatelimits(u32),
11842 #[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"]
11843 TxHwDrops(u32),
11844 #[doc = "Number of packets dropped because they were invalid or malformed."]
11845 TxHwDropErrors(u32),
11846 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
11847 TxCsumNone(u32),
11848 #[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"]
11849 TxNeedsCsum(u32),
11850 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
11851 TxHwGsoPackets(u32),
11852 #[doc = "See `tx-hw-gso-packets`."]
11853 TxHwGsoBytes(u32),
11854 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
11855 TxHwGsoWirePackets(u32),
11856 #[doc = "See `tx-hw-gso-wire-packets`."]
11857 TxHwGsoWireBytes(u32),
11858 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
11859 TxHwDropRatelimits(u32),
11860 #[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"]
11861 TxStop(u32),
11862 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
11863 TxWake(u32),
11864}
11865impl<'a> IterableOpQstatsGetDumpReply<'a> {
11866 #[doc = "ifindex of the netdevice to which stats belong."]
11867 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
11868 let mut iter = self.clone();
11869 iter.pos = 0;
11870 for attr in iter {
11871 if let OpQstatsGetDumpReply::Ifindex(val) = attr? {
11872 return Ok(val);
11873 }
11874 }
11875 Err(ErrorContext::new_missing(
11876 "OpQstatsGetDumpReply",
11877 "Ifindex",
11878 self.orig_loc,
11879 self.buf.as_ptr() as usize,
11880 ))
11881 }
11882 #[doc = "Queue type as rx, tx, for queue-id.\nAssociated type: \"QueueType\" (enum)"]
11883 pub fn get_queue_type(&self) -> Result<u32, ErrorContext> {
11884 let mut iter = self.clone();
11885 iter.pos = 0;
11886 for attr in iter {
11887 if let OpQstatsGetDumpReply::QueueType(val) = attr? {
11888 return Ok(val);
11889 }
11890 }
11891 Err(ErrorContext::new_missing(
11892 "OpQstatsGetDumpReply",
11893 "QueueType",
11894 self.orig_loc,
11895 self.buf.as_ptr() as usize,
11896 ))
11897 }
11898 #[doc = "Queue ID, if stats are scoped to a single queue instance."]
11899 pub fn get_queue_id(&self) -> Result<u32, ErrorContext> {
11900 let mut iter = self.clone();
11901 iter.pos = 0;
11902 for attr in iter {
11903 if let OpQstatsGetDumpReply::QueueId(val) = attr? {
11904 return Ok(val);
11905 }
11906 }
11907 Err(ErrorContext::new_missing(
11908 "OpQstatsGetDumpReply",
11909 "QueueId",
11910 self.orig_loc,
11911 self.buf.as_ptr() as usize,
11912 ))
11913 }
11914 #[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"]
11915 pub fn get_rx_packets(&self) -> Result<u32, ErrorContext> {
11916 let mut iter = self.clone();
11917 iter.pos = 0;
11918 for attr in iter {
11919 if let OpQstatsGetDumpReply::RxPackets(val) = attr? {
11920 return Ok(val);
11921 }
11922 }
11923 Err(ErrorContext::new_missing(
11924 "OpQstatsGetDumpReply",
11925 "RxPackets",
11926 self.orig_loc,
11927 self.buf.as_ptr() as usize,
11928 ))
11929 }
11930 #[doc = "Successfully received bytes, see `rx-packets`."]
11931 pub fn get_rx_bytes(&self) -> Result<u32, ErrorContext> {
11932 let mut iter = self.clone();
11933 iter.pos = 0;
11934 for attr in iter {
11935 if let OpQstatsGetDumpReply::RxBytes(val) = attr? {
11936 return Ok(val);
11937 }
11938 }
11939 Err(ErrorContext::new_missing(
11940 "OpQstatsGetDumpReply",
11941 "RxBytes",
11942 self.orig_loc,
11943 self.buf.as_ptr() as usize,
11944 ))
11945 }
11946 #[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"]
11947 pub fn get_tx_packets(&self) -> Result<u32, ErrorContext> {
11948 let mut iter = self.clone();
11949 iter.pos = 0;
11950 for attr in iter {
11951 if let OpQstatsGetDumpReply::TxPackets(val) = attr? {
11952 return Ok(val);
11953 }
11954 }
11955 Err(ErrorContext::new_missing(
11956 "OpQstatsGetDumpReply",
11957 "TxPackets",
11958 self.orig_loc,
11959 self.buf.as_ptr() as usize,
11960 ))
11961 }
11962 #[doc = "Successfully sent bytes, see `tx-packets`."]
11963 pub fn get_tx_bytes(&self) -> Result<u32, ErrorContext> {
11964 let mut iter = self.clone();
11965 iter.pos = 0;
11966 for attr in iter {
11967 if let OpQstatsGetDumpReply::TxBytes(val) = attr? {
11968 return Ok(val);
11969 }
11970 }
11971 Err(ErrorContext::new_missing(
11972 "OpQstatsGetDumpReply",
11973 "TxBytes",
11974 self.orig_loc,
11975 self.buf.as_ptr() as usize,
11976 ))
11977 }
11978 #[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"]
11979 pub fn get_rx_alloc_fail(&self) -> Result<u32, ErrorContext> {
11980 let mut iter = self.clone();
11981 iter.pos = 0;
11982 for attr in iter {
11983 if let OpQstatsGetDumpReply::RxAllocFail(val) = attr? {
11984 return Ok(val);
11985 }
11986 }
11987 Err(ErrorContext::new_missing(
11988 "OpQstatsGetDumpReply",
11989 "RxAllocFail",
11990 self.orig_loc,
11991 self.buf.as_ptr() as usize,
11992 ))
11993 }
11994 #[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"]
11995 pub fn get_rx_hw_drops(&self) -> Result<u32, ErrorContext> {
11996 let mut iter = self.clone();
11997 iter.pos = 0;
11998 for attr in iter {
11999 if let OpQstatsGetDumpReply::RxHwDrops(val) = attr? {
12000 return Ok(val);
12001 }
12002 }
12003 Err(ErrorContext::new_missing(
12004 "OpQstatsGetDumpReply",
12005 "RxHwDrops",
12006 self.orig_loc,
12007 self.buf.as_ptr() as usize,
12008 ))
12009 }
12010 #[doc = "Number of packets dropped due to transient lack of resources, such as\nbuffer space, host descriptors etc.\n"]
12011 pub fn get_rx_hw_drop_overruns(&self) -> Result<u32, ErrorContext> {
12012 let mut iter = self.clone();
12013 iter.pos = 0;
12014 for attr in iter {
12015 if let OpQstatsGetDumpReply::RxHwDropOverruns(val) = attr? {
12016 return Ok(val);
12017 }
12018 }
12019 Err(ErrorContext::new_missing(
12020 "OpQstatsGetDumpReply",
12021 "RxHwDropOverruns",
12022 self.orig_loc,
12023 self.buf.as_ptr() as usize,
12024 ))
12025 }
12026 #[doc = "Number of packets that were marked as CHECKSUM_COMPLETE."]
12027 pub fn get_rx_csum_complete(&self) -> Result<u32, ErrorContext> {
12028 let mut iter = self.clone();
12029 iter.pos = 0;
12030 for attr in iter {
12031 if let OpQstatsGetDumpReply::RxCsumComplete(val) = attr? {
12032 return Ok(val);
12033 }
12034 }
12035 Err(ErrorContext::new_missing(
12036 "OpQstatsGetDumpReply",
12037 "RxCsumComplete",
12038 self.orig_loc,
12039 self.buf.as_ptr() as usize,
12040 ))
12041 }
12042 #[doc = "Number of packets that were marked as CHECKSUM_UNNECESSARY."]
12043 pub fn get_rx_csum_unnecessary(&self) -> Result<u32, ErrorContext> {
12044 let mut iter = self.clone();
12045 iter.pos = 0;
12046 for attr in iter {
12047 if let OpQstatsGetDumpReply::RxCsumUnnecessary(val) = attr? {
12048 return Ok(val);
12049 }
12050 }
12051 Err(ErrorContext::new_missing(
12052 "OpQstatsGetDumpReply",
12053 "RxCsumUnnecessary",
12054 self.orig_loc,
12055 self.buf.as_ptr() as usize,
12056 ))
12057 }
12058 #[doc = "Number of packets that were not checksummed by device."]
12059 pub fn get_rx_csum_none(&self) -> Result<u32, ErrorContext> {
12060 let mut iter = self.clone();
12061 iter.pos = 0;
12062 for attr in iter {
12063 if let OpQstatsGetDumpReply::RxCsumNone(val) = attr? {
12064 return Ok(val);
12065 }
12066 }
12067 Err(ErrorContext::new_missing(
12068 "OpQstatsGetDumpReply",
12069 "RxCsumNone",
12070 self.orig_loc,
12071 self.buf.as_ptr() as usize,
12072 ))
12073 }
12074 #[doc = "Number of packets with bad checksum. The packets are not discarded,\nbut still delivered to the stack.\n"]
12075 pub fn get_rx_csum_bad(&self) -> Result<u32, ErrorContext> {
12076 let mut iter = self.clone();
12077 iter.pos = 0;
12078 for attr in iter {
12079 if let OpQstatsGetDumpReply::RxCsumBad(val) = attr? {
12080 return Ok(val);
12081 }
12082 }
12083 Err(ErrorContext::new_missing(
12084 "OpQstatsGetDumpReply",
12085 "RxCsumBad",
12086 self.orig_loc,
12087 self.buf.as_ptr() as usize,
12088 ))
12089 }
12090 #[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"]
12091 pub fn get_rx_hw_gro_packets(&self) -> Result<u32, ErrorContext> {
12092 let mut iter = self.clone();
12093 iter.pos = 0;
12094 for attr in iter {
12095 if let OpQstatsGetDumpReply::RxHwGroPackets(val) = attr? {
12096 return Ok(val);
12097 }
12098 }
12099 Err(ErrorContext::new_missing(
12100 "OpQstatsGetDumpReply",
12101 "RxHwGroPackets",
12102 self.orig_loc,
12103 self.buf.as_ptr() as usize,
12104 ))
12105 }
12106 #[doc = "See `rx-hw-gro-packets`."]
12107 pub fn get_rx_hw_gro_bytes(&self) -> Result<u32, ErrorContext> {
12108 let mut iter = self.clone();
12109 iter.pos = 0;
12110 for attr in iter {
12111 if let OpQstatsGetDumpReply::RxHwGroBytes(val) = attr? {
12112 return Ok(val);
12113 }
12114 }
12115 Err(ErrorContext::new_missing(
12116 "OpQstatsGetDumpReply",
12117 "RxHwGroBytes",
12118 self.orig_loc,
12119 self.buf.as_ptr() as usize,
12120 ))
12121 }
12122 #[doc = "Number of packets that were coalesced to bigger packetss with the\nHW-GRO netdevice feature. LRO-coalesced packets are not counted.\n"]
12123 pub fn get_rx_hw_gro_wire_packets(&self) -> Result<u32, ErrorContext> {
12124 let mut iter = self.clone();
12125 iter.pos = 0;
12126 for attr in iter {
12127 if let OpQstatsGetDumpReply::RxHwGroWirePackets(val) = attr? {
12128 return Ok(val);
12129 }
12130 }
12131 Err(ErrorContext::new_missing(
12132 "OpQstatsGetDumpReply",
12133 "RxHwGroWirePackets",
12134 self.orig_loc,
12135 self.buf.as_ptr() as usize,
12136 ))
12137 }
12138 #[doc = "See `rx-hw-gro-wire-packets`."]
12139 pub fn get_rx_hw_gro_wire_bytes(&self) -> Result<u32, ErrorContext> {
12140 let mut iter = self.clone();
12141 iter.pos = 0;
12142 for attr in iter {
12143 if let OpQstatsGetDumpReply::RxHwGroWireBytes(val) = attr? {
12144 return Ok(val);
12145 }
12146 }
12147 Err(ErrorContext::new_missing(
12148 "OpQstatsGetDumpReply",
12149 "RxHwGroWireBytes",
12150 self.orig_loc,
12151 self.buf.as_ptr() as usize,
12152 ))
12153 }
12154 #[doc = "Number of the packets dropped by the device due to the received\npackets bitrate exceeding the device rate limit.\n"]
12155 pub fn get_rx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12156 let mut iter = self.clone();
12157 iter.pos = 0;
12158 for attr in iter {
12159 if let OpQstatsGetDumpReply::RxHwDropRatelimits(val) = attr? {
12160 return Ok(val);
12161 }
12162 }
12163 Err(ErrorContext::new_missing(
12164 "OpQstatsGetDumpReply",
12165 "RxHwDropRatelimits",
12166 self.orig_loc,
12167 self.buf.as_ptr() as usize,
12168 ))
12169 }
12170 #[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"]
12171 pub fn get_tx_hw_drops(&self) -> Result<u32, ErrorContext> {
12172 let mut iter = self.clone();
12173 iter.pos = 0;
12174 for attr in iter {
12175 if let OpQstatsGetDumpReply::TxHwDrops(val) = attr? {
12176 return Ok(val);
12177 }
12178 }
12179 Err(ErrorContext::new_missing(
12180 "OpQstatsGetDumpReply",
12181 "TxHwDrops",
12182 self.orig_loc,
12183 self.buf.as_ptr() as usize,
12184 ))
12185 }
12186 #[doc = "Number of packets dropped because they were invalid or malformed."]
12187 pub fn get_tx_hw_drop_errors(&self) -> Result<u32, ErrorContext> {
12188 let mut iter = self.clone();
12189 iter.pos = 0;
12190 for attr in iter {
12191 if let OpQstatsGetDumpReply::TxHwDropErrors(val) = attr? {
12192 return Ok(val);
12193 }
12194 }
12195 Err(ErrorContext::new_missing(
12196 "OpQstatsGetDumpReply",
12197 "TxHwDropErrors",
12198 self.orig_loc,
12199 self.buf.as_ptr() as usize,
12200 ))
12201 }
12202 #[doc = "Number of packets that did not require the device to calculate the\nchecksum.\n"]
12203 pub fn get_tx_csum_none(&self) -> Result<u32, ErrorContext> {
12204 let mut iter = self.clone();
12205 iter.pos = 0;
12206 for attr in iter {
12207 if let OpQstatsGetDumpReply::TxCsumNone(val) = attr? {
12208 return Ok(val);
12209 }
12210 }
12211 Err(ErrorContext::new_missing(
12212 "OpQstatsGetDumpReply",
12213 "TxCsumNone",
12214 self.orig_loc,
12215 self.buf.as_ptr() as usize,
12216 ))
12217 }
12218 #[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"]
12219 pub fn get_tx_needs_csum(&self) -> Result<u32, ErrorContext> {
12220 let mut iter = self.clone();
12221 iter.pos = 0;
12222 for attr in iter {
12223 if let OpQstatsGetDumpReply::TxNeedsCsum(val) = attr? {
12224 return Ok(val);
12225 }
12226 }
12227 Err(ErrorContext::new_missing(
12228 "OpQstatsGetDumpReply",
12229 "TxNeedsCsum",
12230 self.orig_loc,
12231 self.buf.as_ptr() as usize,
12232 ))
12233 }
12234 #[doc = "Number of packets that necessitated segmentation into smaller packets\nby the device.\n"]
12235 pub fn get_tx_hw_gso_packets(&self) -> Result<u32, ErrorContext> {
12236 let mut iter = self.clone();
12237 iter.pos = 0;
12238 for attr in iter {
12239 if let OpQstatsGetDumpReply::TxHwGsoPackets(val) = attr? {
12240 return Ok(val);
12241 }
12242 }
12243 Err(ErrorContext::new_missing(
12244 "OpQstatsGetDumpReply",
12245 "TxHwGsoPackets",
12246 self.orig_loc,
12247 self.buf.as_ptr() as usize,
12248 ))
12249 }
12250 #[doc = "See `tx-hw-gso-packets`."]
12251 pub fn get_tx_hw_gso_bytes(&self) -> Result<u32, ErrorContext> {
12252 let mut iter = self.clone();
12253 iter.pos = 0;
12254 for attr in iter {
12255 if let OpQstatsGetDumpReply::TxHwGsoBytes(val) = attr? {
12256 return Ok(val);
12257 }
12258 }
12259 Err(ErrorContext::new_missing(
12260 "OpQstatsGetDumpReply",
12261 "TxHwGsoBytes",
12262 self.orig_loc,
12263 self.buf.as_ptr() as usize,
12264 ))
12265 }
12266 #[doc = "Number of wire-sized packets generated by processing\n`tx-hw-gso-packets`\n"]
12267 pub fn get_tx_hw_gso_wire_packets(&self) -> Result<u32, ErrorContext> {
12268 let mut iter = self.clone();
12269 iter.pos = 0;
12270 for attr in iter {
12271 if let OpQstatsGetDumpReply::TxHwGsoWirePackets(val) = attr? {
12272 return Ok(val);
12273 }
12274 }
12275 Err(ErrorContext::new_missing(
12276 "OpQstatsGetDumpReply",
12277 "TxHwGsoWirePackets",
12278 self.orig_loc,
12279 self.buf.as_ptr() as usize,
12280 ))
12281 }
12282 #[doc = "See `tx-hw-gso-wire-packets`."]
12283 pub fn get_tx_hw_gso_wire_bytes(&self) -> Result<u32, ErrorContext> {
12284 let mut iter = self.clone();
12285 iter.pos = 0;
12286 for attr in iter {
12287 if let OpQstatsGetDumpReply::TxHwGsoWireBytes(val) = attr? {
12288 return Ok(val);
12289 }
12290 }
12291 Err(ErrorContext::new_missing(
12292 "OpQstatsGetDumpReply",
12293 "TxHwGsoWireBytes",
12294 self.orig_loc,
12295 self.buf.as_ptr() as usize,
12296 ))
12297 }
12298 #[doc = "Number of the packets dropped by the device due to the transmit\npackets bitrate exceeding the device rate limit.\n"]
12299 pub fn get_tx_hw_drop_ratelimits(&self) -> Result<u32, ErrorContext> {
12300 let mut iter = self.clone();
12301 iter.pos = 0;
12302 for attr in iter {
12303 if let OpQstatsGetDumpReply::TxHwDropRatelimits(val) = attr? {
12304 return Ok(val);
12305 }
12306 }
12307 Err(ErrorContext::new_missing(
12308 "OpQstatsGetDumpReply",
12309 "TxHwDropRatelimits",
12310 self.orig_loc,
12311 self.buf.as_ptr() as usize,
12312 ))
12313 }
12314 #[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"]
12315 pub fn get_tx_stop(&self) -> Result<u32, ErrorContext> {
12316 let mut iter = self.clone();
12317 iter.pos = 0;
12318 for attr in iter {
12319 if let OpQstatsGetDumpReply::TxStop(val) = attr? {
12320 return Ok(val);
12321 }
12322 }
12323 Err(ErrorContext::new_missing(
12324 "OpQstatsGetDumpReply",
12325 "TxStop",
12326 self.orig_loc,
12327 self.buf.as_ptr() as usize,
12328 ))
12329 }
12330 #[doc = "Number of times driver re-started accepting send\nrequests to this queue from the stack.\n"]
12331 pub fn get_tx_wake(&self) -> Result<u32, ErrorContext> {
12332 let mut iter = self.clone();
12333 iter.pos = 0;
12334 for attr in iter {
12335 if let OpQstatsGetDumpReply::TxWake(val) = attr? {
12336 return Ok(val);
12337 }
12338 }
12339 Err(ErrorContext::new_missing(
12340 "OpQstatsGetDumpReply",
12341 "TxWake",
12342 self.orig_loc,
12343 self.buf.as_ptr() as usize,
12344 ))
12345 }
12346}
12347impl OpQstatsGetDumpReply {
12348 pub fn new<'a>(buf: &'a [u8]) -> IterableOpQstatsGetDumpReply<'a> {
12349 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12350 IterableOpQstatsGetDumpReply::with_loc(attrs, buf.as_ptr() as usize)
12351 }
12352 fn attr_from_type(r#type: u16) -> Option<&'static str> {
12353 Qstats::attr_from_type(r#type)
12354 }
12355}
12356#[derive(Clone, Copy, Default)]
12357pub struct IterableOpQstatsGetDumpReply<'a> {
12358 buf: &'a [u8],
12359 pos: usize,
12360 orig_loc: usize,
12361}
12362impl<'a> IterableOpQstatsGetDumpReply<'a> {
12363 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
12364 Self {
12365 buf,
12366 pos: 0,
12367 orig_loc,
12368 }
12369 }
12370 pub fn get_buf(&self) -> &'a [u8] {
12371 self.buf
12372 }
12373}
12374impl<'a> Iterator for IterableOpQstatsGetDumpReply<'a> {
12375 type Item = Result<OpQstatsGetDumpReply, ErrorContext>;
12376 fn next(&mut self) -> Option<Self::Item> {
12377 if self.buf.len() == self.pos {
12378 return None;
12379 }
12380 let pos = self.pos;
12381 let mut r#type = None;
12382 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
12383 r#type = Some(header.r#type);
12384 let res = match header.r#type {
12385 1u16 => OpQstatsGetDumpReply::Ifindex({
12386 let res = parse_u32(next);
12387 let Some(val) = res else { break };
12388 val
12389 }),
12390 2u16 => OpQstatsGetDumpReply::QueueType({
12391 let res = parse_u32(next);
12392 let Some(val) = res else { break };
12393 val
12394 }),
12395 3u16 => OpQstatsGetDumpReply::QueueId({
12396 let res = parse_u32(next);
12397 let Some(val) = res else { break };
12398 val
12399 }),
12400 8u16 => OpQstatsGetDumpReply::RxPackets({
12401 let res = parse_u32(next);
12402 let Some(val) = res else { break };
12403 val
12404 }),
12405 9u16 => OpQstatsGetDumpReply::RxBytes({
12406 let res = parse_u32(next);
12407 let Some(val) = res else { break };
12408 val
12409 }),
12410 10u16 => OpQstatsGetDumpReply::TxPackets({
12411 let res = parse_u32(next);
12412 let Some(val) = res else { break };
12413 val
12414 }),
12415 11u16 => OpQstatsGetDumpReply::TxBytes({
12416 let res = parse_u32(next);
12417 let Some(val) = res else { break };
12418 val
12419 }),
12420 12u16 => OpQstatsGetDumpReply::RxAllocFail({
12421 let res = parse_u32(next);
12422 let Some(val) = res else { break };
12423 val
12424 }),
12425 13u16 => OpQstatsGetDumpReply::RxHwDrops({
12426 let res = parse_u32(next);
12427 let Some(val) = res else { break };
12428 val
12429 }),
12430 14u16 => OpQstatsGetDumpReply::RxHwDropOverruns({
12431 let res = parse_u32(next);
12432 let Some(val) = res else { break };
12433 val
12434 }),
12435 15u16 => OpQstatsGetDumpReply::RxCsumComplete({
12436 let res = parse_u32(next);
12437 let Some(val) = res else { break };
12438 val
12439 }),
12440 16u16 => OpQstatsGetDumpReply::RxCsumUnnecessary({
12441 let res = parse_u32(next);
12442 let Some(val) = res else { break };
12443 val
12444 }),
12445 17u16 => OpQstatsGetDumpReply::RxCsumNone({
12446 let res = parse_u32(next);
12447 let Some(val) = res else { break };
12448 val
12449 }),
12450 18u16 => OpQstatsGetDumpReply::RxCsumBad({
12451 let res = parse_u32(next);
12452 let Some(val) = res else { break };
12453 val
12454 }),
12455 19u16 => OpQstatsGetDumpReply::RxHwGroPackets({
12456 let res = parse_u32(next);
12457 let Some(val) = res else { break };
12458 val
12459 }),
12460 20u16 => OpQstatsGetDumpReply::RxHwGroBytes({
12461 let res = parse_u32(next);
12462 let Some(val) = res else { break };
12463 val
12464 }),
12465 21u16 => OpQstatsGetDumpReply::RxHwGroWirePackets({
12466 let res = parse_u32(next);
12467 let Some(val) = res else { break };
12468 val
12469 }),
12470 22u16 => OpQstatsGetDumpReply::RxHwGroWireBytes({
12471 let res = parse_u32(next);
12472 let Some(val) = res else { break };
12473 val
12474 }),
12475 23u16 => OpQstatsGetDumpReply::RxHwDropRatelimits({
12476 let res = parse_u32(next);
12477 let Some(val) = res else { break };
12478 val
12479 }),
12480 24u16 => OpQstatsGetDumpReply::TxHwDrops({
12481 let res = parse_u32(next);
12482 let Some(val) = res else { break };
12483 val
12484 }),
12485 25u16 => OpQstatsGetDumpReply::TxHwDropErrors({
12486 let res = parse_u32(next);
12487 let Some(val) = res else { break };
12488 val
12489 }),
12490 26u16 => OpQstatsGetDumpReply::TxCsumNone({
12491 let res = parse_u32(next);
12492 let Some(val) = res else { break };
12493 val
12494 }),
12495 27u16 => OpQstatsGetDumpReply::TxNeedsCsum({
12496 let res = parse_u32(next);
12497 let Some(val) = res else { break };
12498 val
12499 }),
12500 28u16 => OpQstatsGetDumpReply::TxHwGsoPackets({
12501 let res = parse_u32(next);
12502 let Some(val) = res else { break };
12503 val
12504 }),
12505 29u16 => OpQstatsGetDumpReply::TxHwGsoBytes({
12506 let res = parse_u32(next);
12507 let Some(val) = res else { break };
12508 val
12509 }),
12510 30u16 => OpQstatsGetDumpReply::TxHwGsoWirePackets({
12511 let res = parse_u32(next);
12512 let Some(val) = res else { break };
12513 val
12514 }),
12515 31u16 => OpQstatsGetDumpReply::TxHwGsoWireBytes({
12516 let res = parse_u32(next);
12517 let Some(val) = res else { break };
12518 val
12519 }),
12520 32u16 => OpQstatsGetDumpReply::TxHwDropRatelimits({
12521 let res = parse_u32(next);
12522 let Some(val) = res else { break };
12523 val
12524 }),
12525 33u16 => OpQstatsGetDumpReply::TxStop({
12526 let res = parse_u32(next);
12527 let Some(val) = res else { break };
12528 val
12529 }),
12530 34u16 => OpQstatsGetDumpReply::TxWake({
12531 let res = parse_u32(next);
12532 let Some(val) = res else { break };
12533 val
12534 }),
12535 n => {
12536 if cfg!(any(test, feature = "deny-unknown-attrs")) {
12537 break;
12538 } else {
12539 continue;
12540 }
12541 }
12542 };
12543 return Some(Ok(res));
12544 }
12545 Some(Err(ErrorContext::new(
12546 "OpQstatsGetDumpReply",
12547 r#type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12548 self.orig_loc,
12549 self.buf.as_ptr().wrapping_add(pos) as usize,
12550 )))
12551 }
12552}
12553impl std::fmt::Debug for IterableOpQstatsGetDumpReply<'_> {
12554 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12555 let mut fmt = f.debug_struct("OpQstatsGetDumpReply");
12556 for attr in self.clone() {
12557 let attr = match attr {
12558 Ok(a) => a,
12559 Err(err) => {
12560 fmt.finish()?;
12561 f.write_str("Err(")?;
12562 err.fmt(f)?;
12563 return f.write_str(")");
12564 }
12565 };
12566 match attr {
12567 OpQstatsGetDumpReply::Ifindex(val) => fmt.field("Ifindex", &val),
12568 OpQstatsGetDumpReply::QueueType(val) => {
12569 fmt.field("QueueType", &FormatEnum(val.into(), QueueType::from_value))
12570 }
12571 OpQstatsGetDumpReply::QueueId(val) => fmt.field("QueueId", &val),
12572 OpQstatsGetDumpReply::RxPackets(val) => fmt.field("RxPackets", &val),
12573 OpQstatsGetDumpReply::RxBytes(val) => fmt.field("RxBytes", &val),
12574 OpQstatsGetDumpReply::TxPackets(val) => fmt.field("TxPackets", &val),
12575 OpQstatsGetDumpReply::TxBytes(val) => fmt.field("TxBytes", &val),
12576 OpQstatsGetDumpReply::RxAllocFail(val) => fmt.field("RxAllocFail", &val),
12577 OpQstatsGetDumpReply::RxHwDrops(val) => fmt.field("RxHwDrops", &val),
12578 OpQstatsGetDumpReply::RxHwDropOverruns(val) => fmt.field("RxHwDropOverruns", &val),
12579 OpQstatsGetDumpReply::RxCsumComplete(val) => fmt.field("RxCsumComplete", &val),
12580 OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12581 fmt.field("RxCsumUnnecessary", &val)
12582 }
12583 OpQstatsGetDumpReply::RxCsumNone(val) => fmt.field("RxCsumNone", &val),
12584 OpQstatsGetDumpReply::RxCsumBad(val) => fmt.field("RxCsumBad", &val),
12585 OpQstatsGetDumpReply::RxHwGroPackets(val) => fmt.field("RxHwGroPackets", &val),
12586 OpQstatsGetDumpReply::RxHwGroBytes(val) => fmt.field("RxHwGroBytes", &val),
12587 OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12588 fmt.field("RxHwGroWirePackets", &val)
12589 }
12590 OpQstatsGetDumpReply::RxHwGroWireBytes(val) => fmt.field("RxHwGroWireBytes", &val),
12591 OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12592 fmt.field("RxHwDropRatelimits", &val)
12593 }
12594 OpQstatsGetDumpReply::TxHwDrops(val) => fmt.field("TxHwDrops", &val),
12595 OpQstatsGetDumpReply::TxHwDropErrors(val) => fmt.field("TxHwDropErrors", &val),
12596 OpQstatsGetDumpReply::TxCsumNone(val) => fmt.field("TxCsumNone", &val),
12597 OpQstatsGetDumpReply::TxNeedsCsum(val) => fmt.field("TxNeedsCsum", &val),
12598 OpQstatsGetDumpReply::TxHwGsoPackets(val) => fmt.field("TxHwGsoPackets", &val),
12599 OpQstatsGetDumpReply::TxHwGsoBytes(val) => fmt.field("TxHwGsoBytes", &val),
12600 OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12601 fmt.field("TxHwGsoWirePackets", &val)
12602 }
12603 OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => fmt.field("TxHwGsoWireBytes", &val),
12604 OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12605 fmt.field("TxHwDropRatelimits", &val)
12606 }
12607 OpQstatsGetDumpReply::TxStop(val) => fmt.field("TxStop", &val),
12608 OpQstatsGetDumpReply::TxWake(val) => fmt.field("TxWake", &val),
12609 };
12610 }
12611 fmt.finish()
12612 }
12613}
12614impl IterableOpQstatsGetDumpReply<'_> {
12615 pub fn lookup_attr(
12616 &self,
12617 offset: usize,
12618 missing_type: Option<u16>,
12619 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12620 let mut stack = Vec::new();
12621 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
12622 if cur == offset + PushBuiltinNfgenmsg::len() {
12623 stack.push(("OpQstatsGetDumpReply", offset));
12624 return (
12625 stack,
12626 missing_type.and_then(|t| OpQstatsGetDumpReply::attr_from_type(t)),
12627 );
12628 }
12629 if cur > offset || cur + self.buf.len() < offset {
12630 return (stack, None);
12631 }
12632 let mut attrs = self.clone();
12633 let mut last_off = cur + attrs.pos;
12634 while let Some(attr) = attrs.next() {
12635 let Ok(attr) = attr else { break };
12636 match attr {
12637 OpQstatsGetDumpReply::Ifindex(val) => {
12638 if last_off == offset {
12639 stack.push(("Ifindex", last_off));
12640 break;
12641 }
12642 }
12643 OpQstatsGetDumpReply::QueueType(val) => {
12644 if last_off == offset {
12645 stack.push(("QueueType", last_off));
12646 break;
12647 }
12648 }
12649 OpQstatsGetDumpReply::QueueId(val) => {
12650 if last_off == offset {
12651 stack.push(("QueueId", last_off));
12652 break;
12653 }
12654 }
12655 OpQstatsGetDumpReply::RxPackets(val) => {
12656 if last_off == offset {
12657 stack.push(("RxPackets", last_off));
12658 break;
12659 }
12660 }
12661 OpQstatsGetDumpReply::RxBytes(val) => {
12662 if last_off == offset {
12663 stack.push(("RxBytes", last_off));
12664 break;
12665 }
12666 }
12667 OpQstatsGetDumpReply::TxPackets(val) => {
12668 if last_off == offset {
12669 stack.push(("TxPackets", last_off));
12670 break;
12671 }
12672 }
12673 OpQstatsGetDumpReply::TxBytes(val) => {
12674 if last_off == offset {
12675 stack.push(("TxBytes", last_off));
12676 break;
12677 }
12678 }
12679 OpQstatsGetDumpReply::RxAllocFail(val) => {
12680 if last_off == offset {
12681 stack.push(("RxAllocFail", last_off));
12682 break;
12683 }
12684 }
12685 OpQstatsGetDumpReply::RxHwDrops(val) => {
12686 if last_off == offset {
12687 stack.push(("RxHwDrops", last_off));
12688 break;
12689 }
12690 }
12691 OpQstatsGetDumpReply::RxHwDropOverruns(val) => {
12692 if last_off == offset {
12693 stack.push(("RxHwDropOverruns", last_off));
12694 break;
12695 }
12696 }
12697 OpQstatsGetDumpReply::RxCsumComplete(val) => {
12698 if last_off == offset {
12699 stack.push(("RxCsumComplete", last_off));
12700 break;
12701 }
12702 }
12703 OpQstatsGetDumpReply::RxCsumUnnecessary(val) => {
12704 if last_off == offset {
12705 stack.push(("RxCsumUnnecessary", last_off));
12706 break;
12707 }
12708 }
12709 OpQstatsGetDumpReply::RxCsumNone(val) => {
12710 if last_off == offset {
12711 stack.push(("RxCsumNone", last_off));
12712 break;
12713 }
12714 }
12715 OpQstatsGetDumpReply::RxCsumBad(val) => {
12716 if last_off == offset {
12717 stack.push(("RxCsumBad", last_off));
12718 break;
12719 }
12720 }
12721 OpQstatsGetDumpReply::RxHwGroPackets(val) => {
12722 if last_off == offset {
12723 stack.push(("RxHwGroPackets", last_off));
12724 break;
12725 }
12726 }
12727 OpQstatsGetDumpReply::RxHwGroBytes(val) => {
12728 if last_off == offset {
12729 stack.push(("RxHwGroBytes", last_off));
12730 break;
12731 }
12732 }
12733 OpQstatsGetDumpReply::RxHwGroWirePackets(val) => {
12734 if last_off == offset {
12735 stack.push(("RxHwGroWirePackets", last_off));
12736 break;
12737 }
12738 }
12739 OpQstatsGetDumpReply::RxHwGroWireBytes(val) => {
12740 if last_off == offset {
12741 stack.push(("RxHwGroWireBytes", last_off));
12742 break;
12743 }
12744 }
12745 OpQstatsGetDumpReply::RxHwDropRatelimits(val) => {
12746 if last_off == offset {
12747 stack.push(("RxHwDropRatelimits", last_off));
12748 break;
12749 }
12750 }
12751 OpQstatsGetDumpReply::TxHwDrops(val) => {
12752 if last_off == offset {
12753 stack.push(("TxHwDrops", last_off));
12754 break;
12755 }
12756 }
12757 OpQstatsGetDumpReply::TxHwDropErrors(val) => {
12758 if last_off == offset {
12759 stack.push(("TxHwDropErrors", last_off));
12760 break;
12761 }
12762 }
12763 OpQstatsGetDumpReply::TxCsumNone(val) => {
12764 if last_off == offset {
12765 stack.push(("TxCsumNone", last_off));
12766 break;
12767 }
12768 }
12769 OpQstatsGetDumpReply::TxNeedsCsum(val) => {
12770 if last_off == offset {
12771 stack.push(("TxNeedsCsum", last_off));
12772 break;
12773 }
12774 }
12775 OpQstatsGetDumpReply::TxHwGsoPackets(val) => {
12776 if last_off == offset {
12777 stack.push(("TxHwGsoPackets", last_off));
12778 break;
12779 }
12780 }
12781 OpQstatsGetDumpReply::TxHwGsoBytes(val) => {
12782 if last_off == offset {
12783 stack.push(("TxHwGsoBytes", last_off));
12784 break;
12785 }
12786 }
12787 OpQstatsGetDumpReply::TxHwGsoWirePackets(val) => {
12788 if last_off == offset {
12789 stack.push(("TxHwGsoWirePackets", last_off));
12790 break;
12791 }
12792 }
12793 OpQstatsGetDumpReply::TxHwGsoWireBytes(val) => {
12794 if last_off == offset {
12795 stack.push(("TxHwGsoWireBytes", last_off));
12796 break;
12797 }
12798 }
12799 OpQstatsGetDumpReply::TxHwDropRatelimits(val) => {
12800 if last_off == offset {
12801 stack.push(("TxHwDropRatelimits", last_off));
12802 break;
12803 }
12804 }
12805 OpQstatsGetDumpReply::TxStop(val) => {
12806 if last_off == offset {
12807 stack.push(("TxStop", last_off));
12808 break;
12809 }
12810 }
12811 OpQstatsGetDumpReply::TxWake(val) => {
12812 if last_off == offset {
12813 stack.push(("TxWake", last_off));
12814 break;
12815 }
12816 }
12817 _ => {}
12818 };
12819 last_off = cur + attrs.pos;
12820 }
12821 if !stack.is_empty() {
12822 stack.push(("OpQstatsGetDumpReply", cur));
12823 }
12824 (stack, None)
12825 }
12826}
12827#[derive(Debug)]
12828pub struct RequestOpQstatsGetDumpRequest<'r> {
12829 request: Request<'r>,
12830}
12831impl<'r> RequestOpQstatsGetDumpRequest<'r> {
12832 pub fn new(mut request: Request<'r>) -> Self {
12833 PushOpQstatsGetDumpRequest::write_header(&mut request.buf_mut());
12834 Self {
12835 request: request.set_dump(),
12836 }
12837 }
12838 pub fn encode(&mut self) -> PushOpQstatsGetDumpRequest<&mut Vec<u8>> {
12839 PushOpQstatsGetDumpRequest::new_without_header(self.request.buf_mut())
12840 }
12841 pub fn into_encoder(self) -> PushOpQstatsGetDumpRequest<RequestBuf<'r>> {
12842 PushOpQstatsGetDumpRequest::new_without_header(self.request.buf)
12843 }
12844}
12845impl NetlinkRequest for RequestOpQstatsGetDumpRequest<'_> {
12846 type ReplyType<'buf> = IterableOpQstatsGetDumpReply<'buf>;
12847 fn protocol(&self) -> Protocol {
12848 Protocol::Generic("netdev".as_bytes())
12849 }
12850 fn flags(&self) -> u16 {
12851 self.request.flags
12852 }
12853 fn payload(&self) -> &[u8] {
12854 self.request.buf()
12855 }
12856 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
12857 OpQstatsGetDumpReply::new(buf)
12858 }
12859 fn lookup(
12860 buf: &[u8],
12861 offset: usize,
12862 missing_type: Option<u16>,
12863 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
12864 OpQstatsGetDumpRequest::new(buf).lookup_attr(offset, missing_type)
12865 }
12866}
12867#[doc = "Bind dmabuf to netdev"]
12868pub struct PushOpBindRxDoRequest<Prev: Rec> {
12869 pub(crate) prev: Option<Prev>,
12870 pub(crate) header_offset: Option<usize>,
12871}
12872impl<Prev: Rec> Rec for PushOpBindRxDoRequest<Prev> {
12873 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
12874 self.prev.as_mut().unwrap().as_rec_mut()
12875 }
12876}
12877impl<Prev: Rec> PushOpBindRxDoRequest<Prev> {
12878 pub fn new(mut prev: Prev) -> Self {
12879 Self::write_header(&mut prev);
12880 Self::new_without_header(prev)
12881 }
12882 fn new_without_header(prev: Prev) -> Self {
12883 Self {
12884 prev: Some(prev),
12885 header_offset: None,
12886 }
12887 }
12888 fn write_header(prev: &mut Prev) {
12889 let mut header = PushBuiltinNfgenmsg::new();
12890 header.set_cmd(13u8);
12891 header.set_version(1u8);
12892 prev.as_rec_mut().extend(header.as_slice());
12893 }
12894 pub fn end_nested(mut self) -> Prev {
12895 let mut prev = self.prev.take().unwrap();
12896 if let Some(header_offset) = &self.header_offset {
12897 finalize_nested_header(prev.as_rec_mut(), *header_offset);
12898 }
12899 prev
12900 }
12901 #[doc = "netdev ifindex to bind the dmabuf to."]
12902 pub fn push_ifindex(mut self, value: u32) -> Self {
12903 push_header(self.as_rec_mut(), 1u16, 4 as u16);
12904 self.as_rec_mut().extend(value.to_ne_bytes());
12905 self
12906 }
12907 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12908 pub fn nested_queues(mut self) -> PushQueueId<Self> {
12909 let header_offset = push_nested_header(self.as_rec_mut(), 2u16);
12910 PushQueueId {
12911 prev: Some(self),
12912 header_offset: Some(header_offset),
12913 }
12914 }
12915 #[doc = "dmabuf file descriptor to bind."]
12916 pub fn push_fd(mut self, value: u32) -> Self {
12917 push_header(self.as_rec_mut(), 3u16, 4 as u16);
12918 self.as_rec_mut().extend(value.to_ne_bytes());
12919 self
12920 }
12921}
12922impl<Prev: Rec> Drop for PushOpBindRxDoRequest<Prev> {
12923 fn drop(&mut self) {
12924 if let Some(prev) = &mut self.prev {
12925 if let Some(header_offset) = &self.header_offset {
12926 finalize_nested_header(prev.as_rec_mut(), *header_offset);
12927 }
12928 }
12929 }
12930}
12931#[doc = "Bind dmabuf to netdev"]
12932#[derive(Clone)]
12933pub enum OpBindRxDoRequest<'a> {
12934 #[doc = "netdev ifindex to bind the dmabuf to."]
12935 Ifindex(u32),
12936 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12937 Queues(IterableQueueId<'a>),
12938 #[doc = "dmabuf file descriptor to bind."]
12939 Fd(u32),
12940}
12941impl<'a> IterableOpBindRxDoRequest<'a> {
12942 #[doc = "netdev ifindex to bind the dmabuf to."]
12943 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
12944 let mut iter = self.clone();
12945 iter.pos = 0;
12946 for attr in iter {
12947 if let OpBindRxDoRequest::Ifindex(val) = attr? {
12948 return Ok(val);
12949 }
12950 }
12951 Err(ErrorContext::new_missing(
12952 "OpBindRxDoRequest",
12953 "Ifindex",
12954 self.orig_loc,
12955 self.buf.as_ptr() as usize,
12956 ))
12957 }
12958 #[doc = "receive queues to bind the dmabuf to.\nAttribute may repeat multiple times (treat it as array)"]
12959 pub fn get_queues(
12960 &self,
12961 ) -> MultiAttrIterable<Self, OpBindRxDoRequest<'a>, IterableQueueId<'a>> {
12962 MultiAttrIterable::new(self.clone(), |variant| {
12963 if let OpBindRxDoRequest::Queues(val) = variant {
12964 Some(val)
12965 } else {
12966 None
12967 }
12968 })
12969 }
12970 #[doc = "dmabuf file descriptor to bind."]
12971 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
12972 let mut iter = self.clone();
12973 iter.pos = 0;
12974 for attr in iter {
12975 if let OpBindRxDoRequest::Fd(val) = attr? {
12976 return Ok(val);
12977 }
12978 }
12979 Err(ErrorContext::new_missing(
12980 "OpBindRxDoRequest",
12981 "Fd",
12982 self.orig_loc,
12983 self.buf.as_ptr() as usize,
12984 ))
12985 }
12986}
12987impl OpBindRxDoRequest<'_> {
12988 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoRequest<'a> {
12989 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
12990 IterableOpBindRxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
12991 }
12992 fn attr_from_type(r#type: u16) -> Option<&'static str> {
12993 Dmabuf::attr_from_type(r#type)
12994 }
12995}
12996#[derive(Clone, Copy, Default)]
12997pub struct IterableOpBindRxDoRequest<'a> {
12998 buf: &'a [u8],
12999 pos: usize,
13000 orig_loc: usize,
13001}
13002impl<'a> IterableOpBindRxDoRequest<'a> {
13003 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13004 Self {
13005 buf,
13006 pos: 0,
13007 orig_loc,
13008 }
13009 }
13010 pub fn get_buf(&self) -> &'a [u8] {
13011 self.buf
13012 }
13013}
13014impl<'a> Iterator for IterableOpBindRxDoRequest<'a> {
13015 type Item = Result<OpBindRxDoRequest<'a>, ErrorContext>;
13016 fn next(&mut self) -> Option<Self::Item> {
13017 if self.buf.len() == self.pos {
13018 return None;
13019 }
13020 let pos = self.pos;
13021 let mut r#type = None;
13022 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13023 r#type = Some(header.r#type);
13024 let res = match header.r#type {
13025 1u16 => OpBindRxDoRequest::Ifindex({
13026 let res = parse_u32(next);
13027 let Some(val) = res else { break };
13028 val
13029 }),
13030 2u16 => OpBindRxDoRequest::Queues({
13031 let res = Some(IterableQueueId::with_loc(next, self.orig_loc));
13032 let Some(val) = res else { break };
13033 val
13034 }),
13035 3u16 => OpBindRxDoRequest::Fd({
13036 let res = parse_u32(next);
13037 let Some(val) = res else { break };
13038 val
13039 }),
13040 n => {
13041 if cfg!(any(test, feature = "deny-unknown-attrs")) {
13042 break;
13043 } else {
13044 continue;
13045 }
13046 }
13047 };
13048 return Some(Ok(res));
13049 }
13050 Some(Err(ErrorContext::new(
13051 "OpBindRxDoRequest",
13052 r#type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13053 self.orig_loc,
13054 self.buf.as_ptr().wrapping_add(pos) as usize,
13055 )))
13056 }
13057}
13058impl<'a> std::fmt::Debug for IterableOpBindRxDoRequest<'_> {
13059 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13060 let mut fmt = f.debug_struct("OpBindRxDoRequest");
13061 for attr in self.clone() {
13062 let attr = match attr {
13063 Ok(a) => a,
13064 Err(err) => {
13065 fmt.finish()?;
13066 f.write_str("Err(")?;
13067 err.fmt(f)?;
13068 return f.write_str(")");
13069 }
13070 };
13071 match attr {
13072 OpBindRxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
13073 OpBindRxDoRequest::Queues(val) => fmt.field("Queues", &val),
13074 OpBindRxDoRequest::Fd(val) => fmt.field("Fd", &val),
13075 };
13076 }
13077 fmt.finish()
13078 }
13079}
13080impl IterableOpBindRxDoRequest<'_> {
13081 pub fn lookup_attr(
13082 &self,
13083 offset: usize,
13084 missing_type: Option<u16>,
13085 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13086 let mut stack = Vec::new();
13087 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13088 if cur == offset + PushBuiltinNfgenmsg::len() {
13089 stack.push(("OpBindRxDoRequest", offset));
13090 return (
13091 stack,
13092 missing_type.and_then(|t| OpBindRxDoRequest::attr_from_type(t)),
13093 );
13094 }
13095 if cur > offset || cur + self.buf.len() < offset {
13096 return (stack, None);
13097 }
13098 let mut attrs = self.clone();
13099 let mut last_off = cur + attrs.pos;
13100 let mut missing = None;
13101 while let Some(attr) = attrs.next() {
13102 let Ok(attr) = attr else { break };
13103 match attr {
13104 OpBindRxDoRequest::Ifindex(val) => {
13105 if last_off == offset {
13106 stack.push(("Ifindex", last_off));
13107 break;
13108 }
13109 }
13110 OpBindRxDoRequest::Queues(val) => {
13111 (stack, missing) = val.lookup_attr(offset, missing_type);
13112 if !stack.is_empty() {
13113 break;
13114 }
13115 }
13116 OpBindRxDoRequest::Fd(val) => {
13117 if last_off == offset {
13118 stack.push(("Fd", last_off));
13119 break;
13120 }
13121 }
13122 _ => {}
13123 };
13124 last_off = cur + attrs.pos;
13125 }
13126 if !stack.is_empty() {
13127 stack.push(("OpBindRxDoRequest", cur));
13128 }
13129 (stack, missing)
13130 }
13131}
13132#[doc = "Bind dmabuf to netdev"]
13133pub struct PushOpBindRxDoReply<Prev: Rec> {
13134 pub(crate) prev: Option<Prev>,
13135 pub(crate) header_offset: Option<usize>,
13136}
13137impl<Prev: Rec> Rec for PushOpBindRxDoReply<Prev> {
13138 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13139 self.prev.as_mut().unwrap().as_rec_mut()
13140 }
13141}
13142impl<Prev: Rec> PushOpBindRxDoReply<Prev> {
13143 pub fn new(mut prev: Prev) -> Self {
13144 Self::write_header(&mut prev);
13145 Self::new_without_header(prev)
13146 }
13147 fn new_without_header(prev: Prev) -> Self {
13148 Self {
13149 prev: Some(prev),
13150 header_offset: None,
13151 }
13152 }
13153 fn write_header(prev: &mut Prev) {
13154 let mut header = PushBuiltinNfgenmsg::new();
13155 header.set_cmd(13u8);
13156 header.set_version(1u8);
13157 prev.as_rec_mut().extend(header.as_slice());
13158 }
13159 pub fn end_nested(mut self) -> Prev {
13160 let mut prev = self.prev.take().unwrap();
13161 if let Some(header_offset) = &self.header_offset {
13162 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13163 }
13164 prev
13165 }
13166 #[doc = "id of the dmabuf binding"]
13167 pub fn push_id(mut self, value: u32) -> Self {
13168 push_header(self.as_rec_mut(), 4u16, 4 as u16);
13169 self.as_rec_mut().extend(value.to_ne_bytes());
13170 self
13171 }
13172}
13173impl<Prev: Rec> Drop for PushOpBindRxDoReply<Prev> {
13174 fn drop(&mut self) {
13175 if let Some(prev) = &mut self.prev {
13176 if let Some(header_offset) = &self.header_offset {
13177 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13178 }
13179 }
13180 }
13181}
13182#[doc = "Bind dmabuf to netdev"]
13183#[derive(Clone)]
13184pub enum OpBindRxDoReply {
13185 #[doc = "id of the dmabuf binding"]
13186 Id(u32),
13187}
13188impl<'a> IterableOpBindRxDoReply<'a> {
13189 #[doc = "id of the dmabuf binding"]
13190 pub fn get_id(&self) -> Result<u32, ErrorContext> {
13191 let mut iter = self.clone();
13192 iter.pos = 0;
13193 for attr in iter {
13194 if let OpBindRxDoReply::Id(val) = attr? {
13195 return Ok(val);
13196 }
13197 }
13198 Err(ErrorContext::new_missing(
13199 "OpBindRxDoReply",
13200 "Id",
13201 self.orig_loc,
13202 self.buf.as_ptr() as usize,
13203 ))
13204 }
13205}
13206impl OpBindRxDoReply {
13207 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindRxDoReply<'a> {
13208 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13209 IterableOpBindRxDoReply::with_loc(attrs, buf.as_ptr() as usize)
13210 }
13211 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13212 Dmabuf::attr_from_type(r#type)
13213 }
13214}
13215#[derive(Clone, Copy, Default)]
13216pub struct IterableOpBindRxDoReply<'a> {
13217 buf: &'a [u8],
13218 pos: usize,
13219 orig_loc: usize,
13220}
13221impl<'a> IterableOpBindRxDoReply<'a> {
13222 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13223 Self {
13224 buf,
13225 pos: 0,
13226 orig_loc,
13227 }
13228 }
13229 pub fn get_buf(&self) -> &'a [u8] {
13230 self.buf
13231 }
13232}
13233impl<'a> Iterator for IterableOpBindRxDoReply<'a> {
13234 type Item = Result<OpBindRxDoReply, ErrorContext>;
13235 fn next(&mut self) -> Option<Self::Item> {
13236 if self.buf.len() == self.pos {
13237 return None;
13238 }
13239 let pos = self.pos;
13240 let mut r#type = None;
13241 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13242 r#type = Some(header.r#type);
13243 let res = match header.r#type {
13244 4u16 => OpBindRxDoReply::Id({
13245 let res = parse_u32(next);
13246 let Some(val) = res else { break };
13247 val
13248 }),
13249 n => {
13250 if cfg!(any(test, feature = "deny-unknown-attrs")) {
13251 break;
13252 } else {
13253 continue;
13254 }
13255 }
13256 };
13257 return Some(Ok(res));
13258 }
13259 Some(Err(ErrorContext::new(
13260 "OpBindRxDoReply",
13261 r#type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13262 self.orig_loc,
13263 self.buf.as_ptr().wrapping_add(pos) as usize,
13264 )))
13265 }
13266}
13267impl std::fmt::Debug for IterableOpBindRxDoReply<'_> {
13268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13269 let mut fmt = f.debug_struct("OpBindRxDoReply");
13270 for attr in self.clone() {
13271 let attr = match attr {
13272 Ok(a) => a,
13273 Err(err) => {
13274 fmt.finish()?;
13275 f.write_str("Err(")?;
13276 err.fmt(f)?;
13277 return f.write_str(")");
13278 }
13279 };
13280 match attr {
13281 OpBindRxDoReply::Id(val) => fmt.field("Id", &val),
13282 };
13283 }
13284 fmt.finish()
13285 }
13286}
13287impl IterableOpBindRxDoReply<'_> {
13288 pub fn lookup_attr(
13289 &self,
13290 offset: usize,
13291 missing_type: Option<u16>,
13292 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13293 let mut stack = Vec::new();
13294 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13295 if cur == offset + PushBuiltinNfgenmsg::len() {
13296 stack.push(("OpBindRxDoReply", offset));
13297 return (
13298 stack,
13299 missing_type.and_then(|t| OpBindRxDoReply::attr_from_type(t)),
13300 );
13301 }
13302 if cur > offset || cur + self.buf.len() < offset {
13303 return (stack, None);
13304 }
13305 let mut attrs = self.clone();
13306 let mut last_off = cur + attrs.pos;
13307 while let Some(attr) = attrs.next() {
13308 let Ok(attr) = attr else { break };
13309 match attr {
13310 OpBindRxDoReply::Id(val) => {
13311 if last_off == offset {
13312 stack.push(("Id", last_off));
13313 break;
13314 }
13315 }
13316 _ => {}
13317 };
13318 last_off = cur + attrs.pos;
13319 }
13320 if !stack.is_empty() {
13321 stack.push(("OpBindRxDoReply", cur));
13322 }
13323 (stack, None)
13324 }
13325}
13326#[derive(Debug)]
13327pub struct RequestOpBindRxDoRequest<'r> {
13328 request: Request<'r>,
13329}
13330impl<'r> RequestOpBindRxDoRequest<'r> {
13331 pub fn new(mut request: Request<'r>) -> Self {
13332 PushOpBindRxDoRequest::write_header(&mut request.buf_mut());
13333 Self { request: request }
13334 }
13335 pub fn encode(&mut self) -> PushOpBindRxDoRequest<&mut Vec<u8>> {
13336 PushOpBindRxDoRequest::new_without_header(self.request.buf_mut())
13337 }
13338 pub fn into_encoder(self) -> PushOpBindRxDoRequest<RequestBuf<'r>> {
13339 PushOpBindRxDoRequest::new_without_header(self.request.buf)
13340 }
13341}
13342impl NetlinkRequest for RequestOpBindRxDoRequest<'_> {
13343 type ReplyType<'buf> = IterableOpBindRxDoReply<'buf>;
13344 fn protocol(&self) -> Protocol {
13345 Protocol::Generic("netdev".as_bytes())
13346 }
13347 fn flags(&self) -> u16 {
13348 self.request.flags
13349 }
13350 fn payload(&self) -> &[u8] {
13351 self.request.buf()
13352 }
13353 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13354 OpBindRxDoReply::new(buf)
13355 }
13356 fn lookup(
13357 buf: &[u8],
13358 offset: usize,
13359 missing_type: Option<u16>,
13360 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13361 OpBindRxDoRequest::new(buf).lookup_attr(offset, missing_type)
13362 }
13363}
13364#[doc = "Set configurable NAPI instance settings."]
13365pub struct PushOpNapiSetDoRequest<Prev: Rec> {
13366 pub(crate) prev: Option<Prev>,
13367 pub(crate) header_offset: Option<usize>,
13368}
13369impl<Prev: Rec> Rec for PushOpNapiSetDoRequest<Prev> {
13370 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13371 self.prev.as_mut().unwrap().as_rec_mut()
13372 }
13373}
13374impl<Prev: Rec> PushOpNapiSetDoRequest<Prev> {
13375 pub fn new(mut prev: Prev) -> Self {
13376 Self::write_header(&mut prev);
13377 Self::new_without_header(prev)
13378 }
13379 fn new_without_header(prev: Prev) -> Self {
13380 Self {
13381 prev: Some(prev),
13382 header_offset: None,
13383 }
13384 }
13385 fn write_header(prev: &mut Prev) {
13386 let mut header = PushBuiltinNfgenmsg::new();
13387 header.set_cmd(14u8);
13388 header.set_version(1u8);
13389 prev.as_rec_mut().extend(header.as_slice());
13390 }
13391 pub fn end_nested(mut self) -> Prev {
13392 let mut prev = self.prev.take().unwrap();
13393 if let Some(header_offset) = &self.header_offset {
13394 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13395 }
13396 prev
13397 }
13398 #[doc = "ID of the NAPI instance."]
13399 pub fn push_id(mut self, value: u32) -> Self {
13400 push_header(self.as_rec_mut(), 2u16, 4 as u16);
13401 self.as_rec_mut().extend(value.to_ne_bytes());
13402 self
13403 }
13404 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13405 pub fn push_defer_hard_irqs(mut self, value: u32) -> Self {
13406 push_header(self.as_rec_mut(), 5u16, 4 as u16);
13407 self.as_rec_mut().extend(value.to_ne_bytes());
13408 self
13409 }
13410 #[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."]
13411 pub fn push_gro_flush_timeout(mut self, value: u32) -> Self {
13412 push_header(self.as_rec_mut(), 6u16, 4 as u16);
13413 self.as_rec_mut().extend(value.to_ne_bytes());
13414 self
13415 }
13416 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13417 pub fn push_irq_suspend_timeout(mut self, value: u32) -> Self {
13418 push_header(self.as_rec_mut(), 7u16, 4 as u16);
13419 self.as_rec_mut().extend(value.to_ne_bytes());
13420 self
13421 }
13422 #[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)"]
13423 pub fn push_threaded(mut self, value: u32) -> Self {
13424 push_header(self.as_rec_mut(), 8u16, 4 as u16);
13425 self.as_rec_mut().extend(value.to_ne_bytes());
13426 self
13427 }
13428}
13429impl<Prev: Rec> Drop for PushOpNapiSetDoRequest<Prev> {
13430 fn drop(&mut self) {
13431 if let Some(prev) = &mut self.prev {
13432 if let Some(header_offset) = &self.header_offset {
13433 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13434 }
13435 }
13436 }
13437}
13438#[doc = "Set configurable NAPI instance settings."]
13439#[derive(Clone)]
13440pub enum OpNapiSetDoRequest {
13441 #[doc = "ID of the NAPI instance."]
13442 Id(u32),
13443 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13444 DeferHardIrqs(u32),
13445 #[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."]
13446 GroFlushTimeout(u32),
13447 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13448 IrqSuspendTimeout(u32),
13449 #[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)"]
13450 Threaded(u32),
13451}
13452impl<'a> IterableOpNapiSetDoRequest<'a> {
13453 #[doc = "ID of the NAPI instance."]
13454 pub fn get_id(&self) -> Result<u32, ErrorContext> {
13455 let mut iter = self.clone();
13456 iter.pos = 0;
13457 for attr in iter {
13458 if let OpNapiSetDoRequest::Id(val) = attr? {
13459 return Ok(val);
13460 }
13461 }
13462 Err(ErrorContext::new_missing(
13463 "OpNapiSetDoRequest",
13464 "Id",
13465 self.orig_loc,
13466 self.buf.as_ptr() as usize,
13467 ))
13468 }
13469 #[doc = "The number of consecutive empty polls before IRQ deferral ends and hardware IRQs are re-enabled."]
13470 pub fn get_defer_hard_irqs(&self) -> Result<u32, ErrorContext> {
13471 let mut iter = self.clone();
13472 iter.pos = 0;
13473 for attr in iter {
13474 if let OpNapiSetDoRequest::DeferHardIrqs(val) = attr? {
13475 return Ok(val);
13476 }
13477 }
13478 Err(ErrorContext::new_missing(
13479 "OpNapiSetDoRequest",
13480 "DeferHardIrqs",
13481 self.orig_loc,
13482 self.buf.as_ptr() as usize,
13483 ))
13484 }
13485 #[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."]
13486 pub fn get_gro_flush_timeout(&self) -> Result<u32, ErrorContext> {
13487 let mut iter = self.clone();
13488 iter.pos = 0;
13489 for attr in iter {
13490 if let OpNapiSetDoRequest::GroFlushTimeout(val) = attr? {
13491 return Ok(val);
13492 }
13493 }
13494 Err(ErrorContext::new_missing(
13495 "OpNapiSetDoRequest",
13496 "GroFlushTimeout",
13497 self.orig_loc,
13498 self.buf.as_ptr() as usize,
13499 ))
13500 }
13501 #[doc = "The timeout, in nanoseconds, of how long to suspend irq processing, if event polling finds events"]
13502 pub fn get_irq_suspend_timeout(&self) -> Result<u32, ErrorContext> {
13503 let mut iter = self.clone();
13504 iter.pos = 0;
13505 for attr in iter {
13506 if let OpNapiSetDoRequest::IrqSuspendTimeout(val) = attr? {
13507 return Ok(val);
13508 }
13509 }
13510 Err(ErrorContext::new_missing(
13511 "OpNapiSetDoRequest",
13512 "IrqSuspendTimeout",
13513 self.orig_loc,
13514 self.buf.as_ptr() as usize,
13515 ))
13516 }
13517 #[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)"]
13518 pub fn get_threaded(&self) -> Result<u32, ErrorContext> {
13519 let mut iter = self.clone();
13520 iter.pos = 0;
13521 for attr in iter {
13522 if let OpNapiSetDoRequest::Threaded(val) = attr? {
13523 return Ok(val);
13524 }
13525 }
13526 Err(ErrorContext::new_missing(
13527 "OpNapiSetDoRequest",
13528 "Threaded",
13529 self.orig_loc,
13530 self.buf.as_ptr() as usize,
13531 ))
13532 }
13533}
13534impl OpNapiSetDoRequest {
13535 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoRequest<'a> {
13536 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13537 IterableOpNapiSetDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13538 }
13539 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13540 Napi::attr_from_type(r#type)
13541 }
13542}
13543#[derive(Clone, Copy, Default)]
13544pub struct IterableOpNapiSetDoRequest<'a> {
13545 buf: &'a [u8],
13546 pos: usize,
13547 orig_loc: usize,
13548}
13549impl<'a> IterableOpNapiSetDoRequest<'a> {
13550 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13551 Self {
13552 buf,
13553 pos: 0,
13554 orig_loc,
13555 }
13556 }
13557 pub fn get_buf(&self) -> &'a [u8] {
13558 self.buf
13559 }
13560}
13561impl<'a> Iterator for IterableOpNapiSetDoRequest<'a> {
13562 type Item = Result<OpNapiSetDoRequest, ErrorContext>;
13563 fn next(&mut self) -> Option<Self::Item> {
13564 if self.buf.len() == self.pos {
13565 return None;
13566 }
13567 let pos = self.pos;
13568 let mut r#type = None;
13569 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13570 r#type = Some(header.r#type);
13571 let res = match header.r#type {
13572 2u16 => OpNapiSetDoRequest::Id({
13573 let res = parse_u32(next);
13574 let Some(val) = res else { break };
13575 val
13576 }),
13577 5u16 => OpNapiSetDoRequest::DeferHardIrqs({
13578 let res = parse_u32(next);
13579 let Some(val) = res else { break };
13580 val
13581 }),
13582 6u16 => OpNapiSetDoRequest::GroFlushTimeout({
13583 let res = parse_u32(next);
13584 let Some(val) = res else { break };
13585 val
13586 }),
13587 7u16 => OpNapiSetDoRequest::IrqSuspendTimeout({
13588 let res = parse_u32(next);
13589 let Some(val) = res else { break };
13590 val
13591 }),
13592 8u16 => OpNapiSetDoRequest::Threaded({
13593 let res = parse_u32(next);
13594 let Some(val) = res else { break };
13595 val
13596 }),
13597 n => {
13598 if cfg!(any(test, feature = "deny-unknown-attrs")) {
13599 break;
13600 } else {
13601 continue;
13602 }
13603 }
13604 };
13605 return Some(Ok(res));
13606 }
13607 Some(Err(ErrorContext::new(
13608 "OpNapiSetDoRequest",
13609 r#type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13610 self.orig_loc,
13611 self.buf.as_ptr().wrapping_add(pos) as usize,
13612 )))
13613 }
13614}
13615impl std::fmt::Debug for IterableOpNapiSetDoRequest<'_> {
13616 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13617 let mut fmt = f.debug_struct("OpNapiSetDoRequest");
13618 for attr in self.clone() {
13619 let attr = match attr {
13620 Ok(a) => a,
13621 Err(err) => {
13622 fmt.finish()?;
13623 f.write_str("Err(")?;
13624 err.fmt(f)?;
13625 return f.write_str(")");
13626 }
13627 };
13628 match attr {
13629 OpNapiSetDoRequest::Id(val) => fmt.field("Id", &val),
13630 OpNapiSetDoRequest::DeferHardIrqs(val) => fmt.field("DeferHardIrqs", &val),
13631 OpNapiSetDoRequest::GroFlushTimeout(val) => fmt.field("GroFlushTimeout", &val),
13632 OpNapiSetDoRequest::IrqSuspendTimeout(val) => fmt.field("IrqSuspendTimeout", &val),
13633 OpNapiSetDoRequest::Threaded(val) => fmt.field(
13634 "Threaded",
13635 &FormatEnum(val.into(), NapiThreaded::from_value),
13636 ),
13637 };
13638 }
13639 fmt.finish()
13640 }
13641}
13642impl IterableOpNapiSetDoRequest<'_> {
13643 pub fn lookup_attr(
13644 &self,
13645 offset: usize,
13646 missing_type: Option<u16>,
13647 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13648 let mut stack = Vec::new();
13649 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13650 if cur == offset + PushBuiltinNfgenmsg::len() {
13651 stack.push(("OpNapiSetDoRequest", offset));
13652 return (
13653 stack,
13654 missing_type.and_then(|t| OpNapiSetDoRequest::attr_from_type(t)),
13655 );
13656 }
13657 if cur > offset || cur + self.buf.len() < offset {
13658 return (stack, None);
13659 }
13660 let mut attrs = self.clone();
13661 let mut last_off = cur + attrs.pos;
13662 while let Some(attr) = attrs.next() {
13663 let Ok(attr) = attr else { break };
13664 match attr {
13665 OpNapiSetDoRequest::Id(val) => {
13666 if last_off == offset {
13667 stack.push(("Id", last_off));
13668 break;
13669 }
13670 }
13671 OpNapiSetDoRequest::DeferHardIrqs(val) => {
13672 if last_off == offset {
13673 stack.push(("DeferHardIrqs", last_off));
13674 break;
13675 }
13676 }
13677 OpNapiSetDoRequest::GroFlushTimeout(val) => {
13678 if last_off == offset {
13679 stack.push(("GroFlushTimeout", last_off));
13680 break;
13681 }
13682 }
13683 OpNapiSetDoRequest::IrqSuspendTimeout(val) => {
13684 if last_off == offset {
13685 stack.push(("IrqSuspendTimeout", last_off));
13686 break;
13687 }
13688 }
13689 OpNapiSetDoRequest::Threaded(val) => {
13690 if last_off == offset {
13691 stack.push(("Threaded", last_off));
13692 break;
13693 }
13694 }
13695 _ => {}
13696 };
13697 last_off = cur + attrs.pos;
13698 }
13699 if !stack.is_empty() {
13700 stack.push(("OpNapiSetDoRequest", cur));
13701 }
13702 (stack, None)
13703 }
13704}
13705#[doc = "Set configurable NAPI instance settings."]
13706pub struct PushOpNapiSetDoReply<Prev: Rec> {
13707 pub(crate) prev: Option<Prev>,
13708 pub(crate) header_offset: Option<usize>,
13709}
13710impl<Prev: Rec> Rec for PushOpNapiSetDoReply<Prev> {
13711 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13712 self.prev.as_mut().unwrap().as_rec_mut()
13713 }
13714}
13715impl<Prev: Rec> PushOpNapiSetDoReply<Prev> {
13716 pub fn new(mut prev: Prev) -> Self {
13717 Self::write_header(&mut prev);
13718 Self::new_without_header(prev)
13719 }
13720 fn new_without_header(prev: Prev) -> Self {
13721 Self {
13722 prev: Some(prev),
13723 header_offset: None,
13724 }
13725 }
13726 fn write_header(prev: &mut Prev) {
13727 let mut header = PushBuiltinNfgenmsg::new();
13728 header.set_cmd(14u8);
13729 header.set_version(1u8);
13730 prev.as_rec_mut().extend(header.as_slice());
13731 }
13732 pub fn end_nested(mut self) -> Prev {
13733 let mut prev = self.prev.take().unwrap();
13734 if let Some(header_offset) = &self.header_offset {
13735 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13736 }
13737 prev
13738 }
13739}
13740impl<Prev: Rec> Drop for PushOpNapiSetDoReply<Prev> {
13741 fn drop(&mut self) {
13742 if let Some(prev) = &mut self.prev {
13743 if let Some(header_offset) = &self.header_offset {
13744 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13745 }
13746 }
13747 }
13748}
13749#[doc = "Set configurable NAPI instance settings."]
13750#[derive(Clone)]
13751pub enum OpNapiSetDoReply {}
13752impl<'a> IterableOpNapiSetDoReply<'a> {}
13753impl OpNapiSetDoReply {
13754 pub fn new<'a>(buf: &'a [u8]) -> IterableOpNapiSetDoReply<'a> {
13755 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13756 IterableOpNapiSetDoReply::with_loc(attrs, buf.as_ptr() as usize)
13757 }
13758 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13759 Napi::attr_from_type(r#type)
13760 }
13761}
13762#[derive(Clone, Copy, Default)]
13763pub struct IterableOpNapiSetDoReply<'a> {
13764 buf: &'a [u8],
13765 pos: usize,
13766 orig_loc: usize,
13767}
13768impl<'a> IterableOpNapiSetDoReply<'a> {
13769 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13770 Self {
13771 buf,
13772 pos: 0,
13773 orig_loc,
13774 }
13775 }
13776 pub fn get_buf(&self) -> &'a [u8] {
13777 self.buf
13778 }
13779}
13780impl<'a> Iterator for IterableOpNapiSetDoReply<'a> {
13781 type Item = Result<OpNapiSetDoReply, ErrorContext>;
13782 fn next(&mut self) -> Option<Self::Item> {
13783 if self.buf.len() == self.pos {
13784 return None;
13785 }
13786 let pos = self.pos;
13787 let mut r#type = None;
13788 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
13789 r#type = Some(header.r#type);
13790 let res = match header.r#type {
13791 n => {
13792 if cfg!(any(test, feature = "deny-unknown-attrs")) {
13793 break;
13794 } else {
13795 continue;
13796 }
13797 }
13798 };
13799 return Some(Ok(res));
13800 }
13801 Some(Err(ErrorContext::new(
13802 "OpNapiSetDoReply",
13803 r#type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13804 self.orig_loc,
13805 self.buf.as_ptr().wrapping_add(pos) as usize,
13806 )))
13807 }
13808}
13809impl std::fmt::Debug for IterableOpNapiSetDoReply<'_> {
13810 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13811 let mut fmt = f.debug_struct("OpNapiSetDoReply");
13812 for attr in self.clone() {
13813 let attr = match attr {
13814 Ok(a) => a,
13815 Err(err) => {
13816 fmt.finish()?;
13817 f.write_str("Err(")?;
13818 err.fmt(f)?;
13819 return f.write_str(")");
13820 }
13821 };
13822 match attr {};
13823 }
13824 fmt.finish()
13825 }
13826}
13827impl IterableOpNapiSetDoReply<'_> {
13828 pub fn lookup_attr(
13829 &self,
13830 offset: usize,
13831 missing_type: Option<u16>,
13832 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13833 let mut stack = Vec::new();
13834 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
13835 if cur == offset + PushBuiltinNfgenmsg::len() {
13836 stack.push(("OpNapiSetDoReply", offset));
13837 return (
13838 stack,
13839 missing_type.and_then(|t| OpNapiSetDoReply::attr_from_type(t)),
13840 );
13841 }
13842 (stack, None)
13843 }
13844}
13845#[derive(Debug)]
13846pub struct RequestOpNapiSetDoRequest<'r> {
13847 request: Request<'r>,
13848}
13849impl<'r> RequestOpNapiSetDoRequest<'r> {
13850 pub fn new(mut request: Request<'r>) -> Self {
13851 PushOpNapiSetDoRequest::write_header(&mut request.buf_mut());
13852 Self { request: request }
13853 }
13854 pub fn encode(&mut self) -> PushOpNapiSetDoRequest<&mut Vec<u8>> {
13855 PushOpNapiSetDoRequest::new_without_header(self.request.buf_mut())
13856 }
13857 pub fn into_encoder(self) -> PushOpNapiSetDoRequest<RequestBuf<'r>> {
13858 PushOpNapiSetDoRequest::new_without_header(self.request.buf)
13859 }
13860}
13861impl NetlinkRequest for RequestOpNapiSetDoRequest<'_> {
13862 type ReplyType<'buf> = IterableOpNapiSetDoReply<'buf>;
13863 fn protocol(&self) -> Protocol {
13864 Protocol::Generic("netdev".as_bytes())
13865 }
13866 fn flags(&self) -> u16 {
13867 self.request.flags
13868 }
13869 fn payload(&self) -> &[u8] {
13870 self.request.buf()
13871 }
13872 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
13873 OpNapiSetDoReply::new(buf)
13874 }
13875 fn lookup(
13876 buf: &[u8],
13877 offset: usize,
13878 missing_type: Option<u16>,
13879 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
13880 OpNapiSetDoRequest::new(buf).lookup_attr(offset, missing_type)
13881 }
13882}
13883#[doc = "Bind dmabuf to netdev for TX"]
13884pub struct PushOpBindTxDoRequest<Prev: Rec> {
13885 pub(crate) prev: Option<Prev>,
13886 pub(crate) header_offset: Option<usize>,
13887}
13888impl<Prev: Rec> Rec for PushOpBindTxDoRequest<Prev> {
13889 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
13890 self.prev.as_mut().unwrap().as_rec_mut()
13891 }
13892}
13893impl<Prev: Rec> PushOpBindTxDoRequest<Prev> {
13894 pub fn new(mut prev: Prev) -> Self {
13895 Self::write_header(&mut prev);
13896 Self::new_without_header(prev)
13897 }
13898 fn new_without_header(prev: Prev) -> Self {
13899 Self {
13900 prev: Some(prev),
13901 header_offset: None,
13902 }
13903 }
13904 fn write_header(prev: &mut Prev) {
13905 let mut header = PushBuiltinNfgenmsg::new();
13906 header.set_cmd(15u8);
13907 header.set_version(1u8);
13908 prev.as_rec_mut().extend(header.as_slice());
13909 }
13910 pub fn end_nested(mut self) -> Prev {
13911 let mut prev = self.prev.take().unwrap();
13912 if let Some(header_offset) = &self.header_offset {
13913 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13914 }
13915 prev
13916 }
13917 #[doc = "netdev ifindex to bind the dmabuf to."]
13918 pub fn push_ifindex(mut self, value: u32) -> Self {
13919 push_header(self.as_rec_mut(), 1u16, 4 as u16);
13920 self.as_rec_mut().extend(value.to_ne_bytes());
13921 self
13922 }
13923 #[doc = "dmabuf file descriptor to bind."]
13924 pub fn push_fd(mut self, value: u32) -> Self {
13925 push_header(self.as_rec_mut(), 3u16, 4 as u16);
13926 self.as_rec_mut().extend(value.to_ne_bytes());
13927 self
13928 }
13929}
13930impl<Prev: Rec> Drop for PushOpBindTxDoRequest<Prev> {
13931 fn drop(&mut self) {
13932 if let Some(prev) = &mut self.prev {
13933 if let Some(header_offset) = &self.header_offset {
13934 finalize_nested_header(prev.as_rec_mut(), *header_offset);
13935 }
13936 }
13937 }
13938}
13939#[doc = "Bind dmabuf to netdev for TX"]
13940#[derive(Clone)]
13941pub enum OpBindTxDoRequest {
13942 #[doc = "netdev ifindex to bind the dmabuf to."]
13943 Ifindex(u32),
13944 #[doc = "dmabuf file descriptor to bind."]
13945 Fd(u32),
13946}
13947impl<'a> IterableOpBindTxDoRequest<'a> {
13948 #[doc = "netdev ifindex to bind the dmabuf to."]
13949 pub fn get_ifindex(&self) -> Result<u32, ErrorContext> {
13950 let mut iter = self.clone();
13951 iter.pos = 0;
13952 for attr in iter {
13953 if let OpBindTxDoRequest::Ifindex(val) = attr? {
13954 return Ok(val);
13955 }
13956 }
13957 Err(ErrorContext::new_missing(
13958 "OpBindTxDoRequest",
13959 "Ifindex",
13960 self.orig_loc,
13961 self.buf.as_ptr() as usize,
13962 ))
13963 }
13964 #[doc = "dmabuf file descriptor to bind."]
13965 pub fn get_fd(&self) -> Result<u32, ErrorContext> {
13966 let mut iter = self.clone();
13967 iter.pos = 0;
13968 for attr in iter {
13969 if let OpBindTxDoRequest::Fd(val) = attr? {
13970 return Ok(val);
13971 }
13972 }
13973 Err(ErrorContext::new_missing(
13974 "OpBindTxDoRequest",
13975 "Fd",
13976 self.orig_loc,
13977 self.buf.as_ptr() as usize,
13978 ))
13979 }
13980}
13981impl OpBindTxDoRequest {
13982 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoRequest<'a> {
13983 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
13984 IterableOpBindTxDoRequest::with_loc(attrs, buf.as_ptr() as usize)
13985 }
13986 fn attr_from_type(r#type: u16) -> Option<&'static str> {
13987 Dmabuf::attr_from_type(r#type)
13988 }
13989}
13990#[derive(Clone, Copy, Default)]
13991pub struct IterableOpBindTxDoRequest<'a> {
13992 buf: &'a [u8],
13993 pos: usize,
13994 orig_loc: usize,
13995}
13996impl<'a> IterableOpBindTxDoRequest<'a> {
13997 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
13998 Self {
13999 buf,
14000 pos: 0,
14001 orig_loc,
14002 }
14003 }
14004 pub fn get_buf(&self) -> &'a [u8] {
14005 self.buf
14006 }
14007}
14008impl<'a> Iterator for IterableOpBindTxDoRequest<'a> {
14009 type Item = Result<OpBindTxDoRequest, ErrorContext>;
14010 fn next(&mut self) -> Option<Self::Item> {
14011 if self.buf.len() == self.pos {
14012 return None;
14013 }
14014 let pos = self.pos;
14015 let mut r#type = None;
14016 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
14017 r#type = Some(header.r#type);
14018 let res = match header.r#type {
14019 1u16 => OpBindTxDoRequest::Ifindex({
14020 let res = parse_u32(next);
14021 let Some(val) = res else { break };
14022 val
14023 }),
14024 3u16 => OpBindTxDoRequest::Fd({
14025 let res = parse_u32(next);
14026 let Some(val) = res else { break };
14027 val
14028 }),
14029 n => {
14030 if cfg!(any(test, feature = "deny-unknown-attrs")) {
14031 break;
14032 } else {
14033 continue;
14034 }
14035 }
14036 };
14037 return Some(Ok(res));
14038 }
14039 Some(Err(ErrorContext::new(
14040 "OpBindTxDoRequest",
14041 r#type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14042 self.orig_loc,
14043 self.buf.as_ptr().wrapping_add(pos) as usize,
14044 )))
14045 }
14046}
14047impl std::fmt::Debug for IterableOpBindTxDoRequest<'_> {
14048 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14049 let mut fmt = f.debug_struct("OpBindTxDoRequest");
14050 for attr in self.clone() {
14051 let attr = match attr {
14052 Ok(a) => a,
14053 Err(err) => {
14054 fmt.finish()?;
14055 f.write_str("Err(")?;
14056 err.fmt(f)?;
14057 return f.write_str(")");
14058 }
14059 };
14060 match attr {
14061 OpBindTxDoRequest::Ifindex(val) => fmt.field("Ifindex", &val),
14062 OpBindTxDoRequest::Fd(val) => fmt.field("Fd", &val),
14063 };
14064 }
14065 fmt.finish()
14066 }
14067}
14068impl IterableOpBindTxDoRequest<'_> {
14069 pub fn lookup_attr(
14070 &self,
14071 offset: usize,
14072 missing_type: Option<u16>,
14073 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14074 let mut stack = Vec::new();
14075 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14076 if cur == offset + PushBuiltinNfgenmsg::len() {
14077 stack.push(("OpBindTxDoRequest", offset));
14078 return (
14079 stack,
14080 missing_type.and_then(|t| OpBindTxDoRequest::attr_from_type(t)),
14081 );
14082 }
14083 if cur > offset || cur + self.buf.len() < offset {
14084 return (stack, None);
14085 }
14086 let mut attrs = self.clone();
14087 let mut last_off = cur + attrs.pos;
14088 while let Some(attr) = attrs.next() {
14089 let Ok(attr) = attr else { break };
14090 match attr {
14091 OpBindTxDoRequest::Ifindex(val) => {
14092 if last_off == offset {
14093 stack.push(("Ifindex", last_off));
14094 break;
14095 }
14096 }
14097 OpBindTxDoRequest::Fd(val) => {
14098 if last_off == offset {
14099 stack.push(("Fd", last_off));
14100 break;
14101 }
14102 }
14103 _ => {}
14104 };
14105 last_off = cur + attrs.pos;
14106 }
14107 if !stack.is_empty() {
14108 stack.push(("OpBindTxDoRequest", cur));
14109 }
14110 (stack, None)
14111 }
14112}
14113#[doc = "Bind dmabuf to netdev for TX"]
14114pub struct PushOpBindTxDoReply<Prev: Rec> {
14115 pub(crate) prev: Option<Prev>,
14116 pub(crate) header_offset: Option<usize>,
14117}
14118impl<Prev: Rec> Rec for PushOpBindTxDoReply<Prev> {
14119 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
14120 self.prev.as_mut().unwrap().as_rec_mut()
14121 }
14122}
14123impl<Prev: Rec> PushOpBindTxDoReply<Prev> {
14124 pub fn new(mut prev: Prev) -> Self {
14125 Self::write_header(&mut prev);
14126 Self::new_without_header(prev)
14127 }
14128 fn new_without_header(prev: Prev) -> Self {
14129 Self {
14130 prev: Some(prev),
14131 header_offset: None,
14132 }
14133 }
14134 fn write_header(prev: &mut Prev) {
14135 let mut header = PushBuiltinNfgenmsg::new();
14136 header.set_cmd(15u8);
14137 header.set_version(1u8);
14138 prev.as_rec_mut().extend(header.as_slice());
14139 }
14140 pub fn end_nested(mut self) -> Prev {
14141 let mut prev = self.prev.take().unwrap();
14142 if let Some(header_offset) = &self.header_offset {
14143 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14144 }
14145 prev
14146 }
14147 #[doc = "id of the dmabuf binding"]
14148 pub fn push_id(mut self, value: u32) -> Self {
14149 push_header(self.as_rec_mut(), 4u16, 4 as u16);
14150 self.as_rec_mut().extend(value.to_ne_bytes());
14151 self
14152 }
14153}
14154impl<Prev: Rec> Drop for PushOpBindTxDoReply<Prev> {
14155 fn drop(&mut self) {
14156 if let Some(prev) = &mut self.prev {
14157 if let Some(header_offset) = &self.header_offset {
14158 finalize_nested_header(prev.as_rec_mut(), *header_offset);
14159 }
14160 }
14161 }
14162}
14163#[doc = "Bind dmabuf to netdev for TX"]
14164#[derive(Clone)]
14165pub enum OpBindTxDoReply {
14166 #[doc = "id of the dmabuf binding"]
14167 Id(u32),
14168}
14169impl<'a> IterableOpBindTxDoReply<'a> {
14170 #[doc = "id of the dmabuf binding"]
14171 pub fn get_id(&self) -> Result<u32, ErrorContext> {
14172 let mut iter = self.clone();
14173 iter.pos = 0;
14174 for attr in iter {
14175 if let OpBindTxDoReply::Id(val) = attr? {
14176 return Ok(val);
14177 }
14178 }
14179 Err(ErrorContext::new_missing(
14180 "OpBindTxDoReply",
14181 "Id",
14182 self.orig_loc,
14183 self.buf.as_ptr() as usize,
14184 ))
14185 }
14186}
14187impl OpBindTxDoReply {
14188 pub fn new<'a>(buf: &'a [u8]) -> IterableOpBindTxDoReply<'a> {
14189 let (_header, attrs) = buf.split_at(buf.len().min(PushBuiltinNfgenmsg::len()));
14190 IterableOpBindTxDoReply::with_loc(attrs, buf.as_ptr() as usize)
14191 }
14192 fn attr_from_type(r#type: u16) -> Option<&'static str> {
14193 Dmabuf::attr_from_type(r#type)
14194 }
14195}
14196#[derive(Clone, Copy, Default)]
14197pub struct IterableOpBindTxDoReply<'a> {
14198 buf: &'a [u8],
14199 pos: usize,
14200 orig_loc: usize,
14201}
14202impl<'a> IterableOpBindTxDoReply<'a> {
14203 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
14204 Self {
14205 buf,
14206 pos: 0,
14207 orig_loc,
14208 }
14209 }
14210 pub fn get_buf(&self) -> &'a [u8] {
14211 self.buf
14212 }
14213}
14214impl<'a> Iterator for IterableOpBindTxDoReply<'a> {
14215 type Item = Result<OpBindTxDoReply, ErrorContext>;
14216 fn next(&mut self) -> Option<Self::Item> {
14217 if self.buf.len() == self.pos {
14218 return None;
14219 }
14220 let pos = self.pos;
14221 let mut r#type = None;
14222 while let Some((header, next)) = chop_header(self.buf, &mut self.pos) {
14223 r#type = Some(header.r#type);
14224 let res = match header.r#type {
14225 4u16 => OpBindTxDoReply::Id({
14226 let res = parse_u32(next);
14227 let Some(val) = res else { break };
14228 val
14229 }),
14230 n => {
14231 if cfg!(any(test, feature = "deny-unknown-attrs")) {
14232 break;
14233 } else {
14234 continue;
14235 }
14236 }
14237 };
14238 return Some(Ok(res));
14239 }
14240 Some(Err(ErrorContext::new(
14241 "OpBindTxDoReply",
14242 r#type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14243 self.orig_loc,
14244 self.buf.as_ptr().wrapping_add(pos) as usize,
14245 )))
14246 }
14247}
14248impl std::fmt::Debug for IterableOpBindTxDoReply<'_> {
14249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14250 let mut fmt = f.debug_struct("OpBindTxDoReply");
14251 for attr in self.clone() {
14252 let attr = match attr {
14253 Ok(a) => a,
14254 Err(err) => {
14255 fmt.finish()?;
14256 f.write_str("Err(")?;
14257 err.fmt(f)?;
14258 return f.write_str(")");
14259 }
14260 };
14261 match attr {
14262 OpBindTxDoReply::Id(val) => fmt.field("Id", &val),
14263 };
14264 }
14265 fmt.finish()
14266 }
14267}
14268impl IterableOpBindTxDoReply<'_> {
14269 pub fn lookup_attr(
14270 &self,
14271 offset: usize,
14272 missing_type: Option<u16>,
14273 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14274 let mut stack = Vec::new();
14275 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
14276 if cur == offset + PushBuiltinNfgenmsg::len() {
14277 stack.push(("OpBindTxDoReply", offset));
14278 return (
14279 stack,
14280 missing_type.and_then(|t| OpBindTxDoReply::attr_from_type(t)),
14281 );
14282 }
14283 if cur > offset || cur + self.buf.len() < offset {
14284 return (stack, None);
14285 }
14286 let mut attrs = self.clone();
14287 let mut last_off = cur + attrs.pos;
14288 while let Some(attr) = attrs.next() {
14289 let Ok(attr) = attr else { break };
14290 match attr {
14291 OpBindTxDoReply::Id(val) => {
14292 if last_off == offset {
14293 stack.push(("Id", last_off));
14294 break;
14295 }
14296 }
14297 _ => {}
14298 };
14299 last_off = cur + attrs.pos;
14300 }
14301 if !stack.is_empty() {
14302 stack.push(("OpBindTxDoReply", cur));
14303 }
14304 (stack, None)
14305 }
14306}
14307#[derive(Debug)]
14308pub struct RequestOpBindTxDoRequest<'r> {
14309 request: Request<'r>,
14310}
14311impl<'r> RequestOpBindTxDoRequest<'r> {
14312 pub fn new(mut request: Request<'r>) -> Self {
14313 PushOpBindTxDoRequest::write_header(&mut request.buf_mut());
14314 Self { request: request }
14315 }
14316 pub fn encode(&mut self) -> PushOpBindTxDoRequest<&mut Vec<u8>> {
14317 PushOpBindTxDoRequest::new_without_header(self.request.buf_mut())
14318 }
14319 pub fn into_encoder(self) -> PushOpBindTxDoRequest<RequestBuf<'r>> {
14320 PushOpBindTxDoRequest::new_without_header(self.request.buf)
14321 }
14322}
14323impl NetlinkRequest for RequestOpBindTxDoRequest<'_> {
14324 type ReplyType<'buf> = IterableOpBindTxDoReply<'buf>;
14325 fn protocol(&self) -> Protocol {
14326 Protocol::Generic("netdev".as_bytes())
14327 }
14328 fn flags(&self) -> u16 {
14329 self.request.flags
14330 }
14331 fn payload(&self) -> &[u8] {
14332 self.request.buf()
14333 }
14334 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
14335 OpBindTxDoReply::new(buf)
14336 }
14337 fn lookup(
14338 buf: &[u8],
14339 offset: usize,
14340 missing_type: Option<u16>,
14341 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
14342 OpBindTxDoRequest::new(buf).lookup_attr(offset, missing_type)
14343 }
14344}
14345use crate::traits::LookupFn;
14346use crate::utils::RequestBuf;
14347#[derive(Debug)]
14348pub struct Request<'buf> {
14349 buf: RequestBuf<'buf>,
14350 flags: u16,
14351 writeback: Option<&'buf mut Option<RequestInfo>>,
14352}
14353#[allow(unused)]
14354#[derive(Debug, Clone)]
14355pub struct RequestInfo {
14356 protocol: Protocol,
14357 flags: u16,
14358 name: &'static str,
14359 lookup: LookupFn,
14360}
14361impl Request<'static> {
14362 pub fn new() -> Self {
14363 Self::new_from_buf(Vec::new())
14364 }
14365 pub fn new_from_buf(buf: Vec<u8>) -> Self {
14366 Self {
14367 flags: 0,
14368 buf: RequestBuf::Own(buf),
14369 writeback: None,
14370 }
14371 }
14372 pub fn into_buf(self) -> Vec<u8> {
14373 match self.buf {
14374 RequestBuf::Own(buf) => buf,
14375 _ => unreachable!(),
14376 }
14377 }
14378}
14379impl<'buf> Request<'buf> {
14380 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
14381 buf.clear();
14382 Self::new_extend(buf)
14383 }
14384 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
14385 Self {
14386 flags: 0,
14387 buf: RequestBuf::Ref(buf),
14388 writeback: None,
14389 }
14390 }
14391 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
14392 let Some(writeback) = &mut self.writeback else {
14393 return;
14394 };
14395 **writeback = Some(RequestInfo {
14396 protocol,
14397 flags: self.flags,
14398 name,
14399 lookup,
14400 })
14401 }
14402 pub fn buf(&self) -> &Vec<u8> {
14403 self.buf.buf()
14404 }
14405 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
14406 self.buf.buf_mut()
14407 }
14408 #[doc = "Set `NLM_F_CREATE` flag"]
14409 pub fn set_create(mut self) -> Self {
14410 self.flags |= consts::NLM_F_CREATE as u16;
14411 self
14412 }
14413 #[doc = "Set `NLM_F_EXCL` flag"]
14414 pub fn set_excl(mut self) -> Self {
14415 self.flags |= consts::NLM_F_EXCL as u16;
14416 self
14417 }
14418 #[doc = "Set `NLM_F_REPLACE` flag"]
14419 pub fn set_replace(mut self) -> Self {
14420 self.flags |= consts::NLM_F_REPLACE as u16;
14421 self
14422 }
14423 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
14424 pub fn set_change(self) -> Self {
14425 self.set_create().set_replace()
14426 }
14427 #[doc = "Set `NLM_F_APPEND` flag"]
14428 pub fn set_append(mut self) -> Self {
14429 self.flags |= consts::NLM_F_APPEND as u16;
14430 self
14431 }
14432 #[doc = "Set `NLM_F_DUMP` flag"]
14433 fn set_dump(mut self) -> Self {
14434 self.flags |= consts::NLM_F_DUMP as u16;
14435 self
14436 }
14437 pub fn op_dev_get_dump_request(self) -> RequestOpDevGetDumpRequest<'buf> {
14438 let mut res = RequestOpDevGetDumpRequest::new(self);
14439 res.request.do_writeback(
14440 res.protocol(),
14441 "op-dev-get-dump-request",
14442 RequestOpDevGetDumpRequest::lookup,
14443 );
14444 res
14445 }
14446 pub fn op_dev_get_do_request(self) -> RequestOpDevGetDoRequest<'buf> {
14447 let mut res = RequestOpDevGetDoRequest::new(self);
14448 res.request.do_writeback(
14449 res.protocol(),
14450 "op-dev-get-do-request",
14451 RequestOpDevGetDoRequest::lookup,
14452 );
14453 res
14454 }
14455 pub fn op_page_pool_get_dump_request(self) -> RequestOpPagePoolGetDumpRequest<'buf> {
14456 let mut res = RequestOpPagePoolGetDumpRequest::new(self);
14457 res.request.do_writeback(
14458 res.protocol(),
14459 "op-page-pool-get-dump-request",
14460 RequestOpPagePoolGetDumpRequest::lookup,
14461 );
14462 res
14463 }
14464 pub fn op_page_pool_get_do_request(self) -> RequestOpPagePoolGetDoRequest<'buf> {
14465 let mut res = RequestOpPagePoolGetDoRequest::new(self);
14466 res.request.do_writeback(
14467 res.protocol(),
14468 "op-page-pool-get-do-request",
14469 RequestOpPagePoolGetDoRequest::lookup,
14470 );
14471 res
14472 }
14473 pub fn op_page_pool_stats_get_dump_request(self) -> RequestOpPagePoolStatsGetDumpRequest<'buf> {
14474 let mut res = RequestOpPagePoolStatsGetDumpRequest::new(self);
14475 res.request.do_writeback(
14476 res.protocol(),
14477 "op-page-pool-stats-get-dump-request",
14478 RequestOpPagePoolStatsGetDumpRequest::lookup,
14479 );
14480 res
14481 }
14482 pub fn op_page_pool_stats_get_do_request(self) -> RequestOpPagePoolStatsGetDoRequest<'buf> {
14483 let mut res = RequestOpPagePoolStatsGetDoRequest::new(self);
14484 res.request.do_writeback(
14485 res.protocol(),
14486 "op-page-pool-stats-get-do-request",
14487 RequestOpPagePoolStatsGetDoRequest::lookup,
14488 );
14489 res
14490 }
14491 pub fn op_queue_get_dump_request(self) -> RequestOpQueueGetDumpRequest<'buf> {
14492 let mut res = RequestOpQueueGetDumpRequest::new(self);
14493 res.request.do_writeback(
14494 res.protocol(),
14495 "op-queue-get-dump-request",
14496 RequestOpQueueGetDumpRequest::lookup,
14497 );
14498 res
14499 }
14500 pub fn op_queue_get_do_request(self) -> RequestOpQueueGetDoRequest<'buf> {
14501 let mut res = RequestOpQueueGetDoRequest::new(self);
14502 res.request.do_writeback(
14503 res.protocol(),
14504 "op-queue-get-do-request",
14505 RequestOpQueueGetDoRequest::lookup,
14506 );
14507 res
14508 }
14509 pub fn op_napi_get_dump_request(self) -> RequestOpNapiGetDumpRequest<'buf> {
14510 let mut res = RequestOpNapiGetDumpRequest::new(self);
14511 res.request.do_writeback(
14512 res.protocol(),
14513 "op-napi-get-dump-request",
14514 RequestOpNapiGetDumpRequest::lookup,
14515 );
14516 res
14517 }
14518 pub fn op_napi_get_do_request(self) -> RequestOpNapiGetDoRequest<'buf> {
14519 let mut res = RequestOpNapiGetDoRequest::new(self);
14520 res.request.do_writeback(
14521 res.protocol(),
14522 "op-napi-get-do-request",
14523 RequestOpNapiGetDoRequest::lookup,
14524 );
14525 res
14526 }
14527 pub fn op_qstats_get_dump_request(self) -> RequestOpQstatsGetDumpRequest<'buf> {
14528 let mut res = RequestOpQstatsGetDumpRequest::new(self);
14529 res.request.do_writeback(
14530 res.protocol(),
14531 "op-qstats-get-dump-request",
14532 RequestOpQstatsGetDumpRequest::lookup,
14533 );
14534 res
14535 }
14536 pub fn op_bind_rx_do_request(self) -> RequestOpBindRxDoRequest<'buf> {
14537 let mut res = RequestOpBindRxDoRequest::new(self);
14538 res.request.do_writeback(
14539 res.protocol(),
14540 "op-bind-rx-do-request",
14541 RequestOpBindRxDoRequest::lookup,
14542 );
14543 res
14544 }
14545 pub fn op_napi_set_do_request(self) -> RequestOpNapiSetDoRequest<'buf> {
14546 let mut res = RequestOpNapiSetDoRequest::new(self);
14547 res.request.do_writeback(
14548 res.protocol(),
14549 "op-napi-set-do-request",
14550 RequestOpNapiSetDoRequest::lookup,
14551 );
14552 res
14553 }
14554 pub fn op_bind_tx_do_request(self) -> RequestOpBindTxDoRequest<'buf> {
14555 let mut res = RequestOpBindTxDoRequest::new(self);
14556 res.request.do_writeback(
14557 res.protocol(),
14558 "op-bind-tx-do-request",
14559 RequestOpBindTxDoRequest::lookup,
14560 );
14561 res
14562 }
14563}