Skip to main content

netlink_bindings/tcp_metrics/
mod.rs

1#![doc = "Management interface for TCP metrics.\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12    consts,
13    traits::{NetlinkRequest, Protocol},
14    utils::*,
15};
16pub const PROTONAME: &str = "tcp_metrics";
17pub const PROTONAME_CSTR: &CStr = c"tcp_metrics";
18pub const TCP_FASTOPEN_COOKIE_MAX: u64 = 16u64;
19#[derive(Clone)]
20pub enum TcpMetrics<'a> {
21    AddrIpv4(std::net::Ipv4Addr),
22    AddrIpv6(std::net::Ipv6Addr),
23    Age(u64),
24    #[doc = "unused\n"]
25    TwTsval(u32),
26    #[doc = "unused\n"]
27    TwTsStamp(i32),
28    Vals(IterableMetrics<'a>),
29    FopenMss(u16),
30    FopenSynDrops(u16),
31    FopenSynDropTs(u64),
32    FopenCookie(&'a [u8]),
33    SaddrIpv4(std::net::Ipv4Addr),
34    SaddrIpv6(std::net::Ipv6Addr),
35    Pad(&'a [u8]),
36}
37impl<'a> IterableTcpMetrics<'a> {
38    pub fn get_addr_ipv4(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
39        let mut iter = self.clone();
40        iter.pos = 0;
41        for attr in iter {
42            if let Ok(TcpMetrics::AddrIpv4(val)) = attr {
43                return Ok(val);
44            }
45        }
46        Err(ErrorContext::new_missing(
47            "TcpMetrics",
48            "AddrIpv4",
49            self.orig_loc,
50            self.buf.as_ptr() as usize,
51        ))
52    }
53    pub fn get_addr_ipv6(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
54        let mut iter = self.clone();
55        iter.pos = 0;
56        for attr in iter {
57            if let Ok(TcpMetrics::AddrIpv6(val)) = attr {
58                return Ok(val);
59            }
60        }
61        Err(ErrorContext::new_missing(
62            "TcpMetrics",
63            "AddrIpv6",
64            self.orig_loc,
65            self.buf.as_ptr() as usize,
66        ))
67    }
68    pub fn get_age(&self) -> Result<u64, ErrorContext> {
69        let mut iter = self.clone();
70        iter.pos = 0;
71        for attr in iter {
72            if let Ok(TcpMetrics::Age(val)) = attr {
73                return Ok(val);
74            }
75        }
76        Err(ErrorContext::new_missing(
77            "TcpMetrics",
78            "Age",
79            self.orig_loc,
80            self.buf.as_ptr() as usize,
81        ))
82    }
83    #[doc = "unused\n"]
84    pub fn get_tw_tsval(&self) -> Result<u32, ErrorContext> {
85        let mut iter = self.clone();
86        iter.pos = 0;
87        for attr in iter {
88            if let Ok(TcpMetrics::TwTsval(val)) = attr {
89                return Ok(val);
90            }
91        }
92        Err(ErrorContext::new_missing(
93            "TcpMetrics",
94            "TwTsval",
95            self.orig_loc,
96            self.buf.as_ptr() as usize,
97        ))
98    }
99    #[doc = "unused\n"]
100    pub fn get_tw_ts_stamp(&self) -> Result<i32, ErrorContext> {
101        let mut iter = self.clone();
102        iter.pos = 0;
103        for attr in iter {
104            if let Ok(TcpMetrics::TwTsStamp(val)) = attr {
105                return Ok(val);
106            }
107        }
108        Err(ErrorContext::new_missing(
109            "TcpMetrics",
110            "TwTsStamp",
111            self.orig_loc,
112            self.buf.as_ptr() as usize,
113        ))
114    }
115    pub fn get_vals(&self) -> Result<IterableMetrics<'a>, ErrorContext> {
116        let mut iter = self.clone();
117        iter.pos = 0;
118        for attr in iter {
119            if let Ok(TcpMetrics::Vals(val)) = attr {
120                return Ok(val);
121            }
122        }
123        Err(ErrorContext::new_missing(
124            "TcpMetrics",
125            "Vals",
126            self.orig_loc,
127            self.buf.as_ptr() as usize,
128        ))
129    }
130    pub fn get_fopen_mss(&self) -> Result<u16, ErrorContext> {
131        let mut iter = self.clone();
132        iter.pos = 0;
133        for attr in iter {
134            if let Ok(TcpMetrics::FopenMss(val)) = attr {
135                return Ok(val);
136            }
137        }
138        Err(ErrorContext::new_missing(
139            "TcpMetrics",
140            "FopenMss",
141            self.orig_loc,
142            self.buf.as_ptr() as usize,
143        ))
144    }
145    pub fn get_fopen_syn_drops(&self) -> Result<u16, ErrorContext> {
146        let mut iter = self.clone();
147        iter.pos = 0;
148        for attr in iter {
149            if let Ok(TcpMetrics::FopenSynDrops(val)) = attr {
150                return Ok(val);
151            }
152        }
153        Err(ErrorContext::new_missing(
154            "TcpMetrics",
155            "FopenSynDrops",
156            self.orig_loc,
157            self.buf.as_ptr() as usize,
158        ))
159    }
160    pub fn get_fopen_syn_drop_ts(&self) -> Result<u64, ErrorContext> {
161        let mut iter = self.clone();
162        iter.pos = 0;
163        for attr in iter {
164            if let Ok(TcpMetrics::FopenSynDropTs(val)) = attr {
165                return Ok(val);
166            }
167        }
168        Err(ErrorContext::new_missing(
169            "TcpMetrics",
170            "FopenSynDropTs",
171            self.orig_loc,
172            self.buf.as_ptr() as usize,
173        ))
174    }
175    pub fn get_fopen_cookie(&self) -> Result<&'a [u8], ErrorContext> {
176        let mut iter = self.clone();
177        iter.pos = 0;
178        for attr in iter {
179            if let Ok(TcpMetrics::FopenCookie(val)) = attr {
180                return Ok(val);
181            }
182        }
183        Err(ErrorContext::new_missing(
184            "TcpMetrics",
185            "FopenCookie",
186            self.orig_loc,
187            self.buf.as_ptr() as usize,
188        ))
189    }
190    pub fn get_saddr_ipv4(&self) -> Result<std::net::Ipv4Addr, ErrorContext> {
191        let mut iter = self.clone();
192        iter.pos = 0;
193        for attr in iter {
194            if let Ok(TcpMetrics::SaddrIpv4(val)) = attr {
195                return Ok(val);
196            }
197        }
198        Err(ErrorContext::new_missing(
199            "TcpMetrics",
200            "SaddrIpv4",
201            self.orig_loc,
202            self.buf.as_ptr() as usize,
203        ))
204    }
205    pub fn get_saddr_ipv6(&self) -> Result<std::net::Ipv6Addr, ErrorContext> {
206        let mut iter = self.clone();
207        iter.pos = 0;
208        for attr in iter {
209            if let Ok(TcpMetrics::SaddrIpv6(val)) = attr {
210                return Ok(val);
211            }
212        }
213        Err(ErrorContext::new_missing(
214            "TcpMetrics",
215            "SaddrIpv6",
216            self.orig_loc,
217            self.buf.as_ptr() as usize,
218        ))
219    }
220    pub fn get_pad(&self) -> Result<&'a [u8], ErrorContext> {
221        let mut iter = self.clone();
222        iter.pos = 0;
223        for attr in iter {
224            if let Ok(TcpMetrics::Pad(val)) = attr {
225                return Ok(val);
226            }
227        }
228        Err(ErrorContext::new_missing(
229            "TcpMetrics",
230            "Pad",
231            self.orig_loc,
232            self.buf.as_ptr() as usize,
233        ))
234    }
235}
236impl TcpMetrics<'_> {
237    pub fn new<'a>(buf: &'a [u8]) -> IterableTcpMetrics<'a> {
238        IterableTcpMetrics::with_loc(buf, buf.as_ptr() as usize)
239    }
240    fn attr_from_type(r#type: u16) -> Option<&'static str> {
241        let res = match r#type {
242            1u16 => "AddrIpv4",
243            2u16 => "AddrIpv6",
244            3u16 => "Age",
245            4u16 => "TwTsval",
246            5u16 => "TwTsStamp",
247            6u16 => "Vals",
248            7u16 => "FopenMss",
249            8u16 => "FopenSynDrops",
250            9u16 => "FopenSynDropTs",
251            10u16 => "FopenCookie",
252            11u16 => "SaddrIpv4",
253            12u16 => "SaddrIpv6",
254            13u16 => "Pad",
255            _ => return None,
256        };
257        Some(res)
258    }
259}
260#[derive(Clone, Copy, Default)]
261pub struct IterableTcpMetrics<'a> {
262    buf: &'a [u8],
263    pos: usize,
264    orig_loc: usize,
265}
266impl<'a> IterableTcpMetrics<'a> {
267    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
268        Self {
269            buf,
270            pos: 0,
271            orig_loc,
272        }
273    }
274    pub fn get_buf(&self) -> &'a [u8] {
275        self.buf
276    }
277}
278impl<'a> Iterator for IterableTcpMetrics<'a> {
279    type Item = Result<TcpMetrics<'a>, ErrorContext>;
280    fn next(&mut self) -> Option<Self::Item> {
281        let mut pos;
282        let mut r#type;
283        loop {
284            pos = self.pos;
285            r#type = None;
286            if self.buf.len() == self.pos {
287                return None;
288            }
289            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
290                self.pos = self.buf.len();
291                break;
292            };
293            r#type = Some(header.r#type);
294            let res = match header.r#type {
295                1u16 => TcpMetrics::AddrIpv4({
296                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
297                    let Some(val) = res else { break };
298                    val
299                }),
300                2u16 => TcpMetrics::AddrIpv6({
301                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
302                    let Some(val) = res else { break };
303                    val
304                }),
305                3u16 => TcpMetrics::Age({
306                    let res = parse_u64(next);
307                    let Some(val) = res else { break };
308                    val
309                }),
310                4u16 => TcpMetrics::TwTsval({
311                    let res = parse_u32(next);
312                    let Some(val) = res else { break };
313                    val
314                }),
315                5u16 => TcpMetrics::TwTsStamp({
316                    let res = parse_i32(next);
317                    let Some(val) = res else { break };
318                    val
319                }),
320                6u16 => TcpMetrics::Vals({
321                    let res = Some(IterableMetrics::with_loc(next, self.orig_loc));
322                    let Some(val) = res else { break };
323                    val
324                }),
325                7u16 => TcpMetrics::FopenMss({
326                    let res = parse_u16(next);
327                    let Some(val) = res else { break };
328                    val
329                }),
330                8u16 => TcpMetrics::FopenSynDrops({
331                    let res = parse_u16(next);
332                    let Some(val) = res else { break };
333                    val
334                }),
335                9u16 => TcpMetrics::FopenSynDropTs({
336                    let res = parse_u64(next);
337                    let Some(val) = res else { break };
338                    val
339                }),
340                10u16 => TcpMetrics::FopenCookie({
341                    let res = Some(next);
342                    let Some(val) = res else { break };
343                    val
344                }),
345                11u16 => TcpMetrics::SaddrIpv4({
346                    let res = parse_be_u32(next).map(Ipv4Addr::from_bits);
347                    let Some(val) = res else { break };
348                    val
349                }),
350                12u16 => TcpMetrics::SaddrIpv6({
351                    let res = parse_be_u128(next).map(Ipv6Addr::from_bits);
352                    let Some(val) = res else { break };
353                    val
354                }),
355                13u16 => TcpMetrics::Pad({
356                    let res = Some(next);
357                    let Some(val) = res else { break };
358                    val
359                }),
360                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
361                n => continue,
362            };
363            return Some(Ok(res));
364        }
365        Some(Err(ErrorContext::new(
366            "TcpMetrics",
367            r#type.and_then(|t| TcpMetrics::attr_from_type(t)),
368            self.orig_loc,
369            self.buf.as_ptr().wrapping_add(pos) as usize,
370        )))
371    }
372}
373impl<'a> std::fmt::Debug for IterableTcpMetrics<'_> {
374    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
375        let mut fmt = f.debug_struct("TcpMetrics");
376        for attr in self.clone() {
377            let attr = match attr {
378                Ok(a) => a,
379                Err(err) => {
380                    fmt.finish()?;
381                    f.write_str("Err(")?;
382                    err.fmt(f)?;
383                    return f.write_str(")");
384                }
385            };
386            match attr {
387                TcpMetrics::AddrIpv4(val) => fmt.field("AddrIpv4", &val),
388                TcpMetrics::AddrIpv6(val) => fmt.field("AddrIpv6", &val),
389                TcpMetrics::Age(val) => fmt.field("Age", &val),
390                TcpMetrics::TwTsval(val) => fmt.field("TwTsval", &val),
391                TcpMetrics::TwTsStamp(val) => fmt.field("TwTsStamp", &val),
392                TcpMetrics::Vals(val) => fmt.field("Vals", &val),
393                TcpMetrics::FopenMss(val) => fmt.field("FopenMss", &val),
394                TcpMetrics::FopenSynDrops(val) => fmt.field("FopenSynDrops", &val),
395                TcpMetrics::FopenSynDropTs(val) => fmt.field("FopenSynDropTs", &val),
396                TcpMetrics::FopenCookie(val) => fmt.field("FopenCookie", &val),
397                TcpMetrics::SaddrIpv4(val) => fmt.field("SaddrIpv4", &val),
398                TcpMetrics::SaddrIpv6(val) => fmt.field("SaddrIpv6", &val),
399                TcpMetrics::Pad(val) => fmt.field("Pad", &val),
400            };
401        }
402        fmt.finish()
403    }
404}
405impl IterableTcpMetrics<'_> {
406    pub fn lookup_attr(
407        &self,
408        offset: usize,
409        missing_type: Option<u16>,
410    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
411        let mut stack = Vec::new();
412        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
413        if missing_type.is_some() && cur == offset {
414            stack.push(("TcpMetrics", offset));
415            return (
416                stack,
417                missing_type.and_then(|t| TcpMetrics::attr_from_type(t)),
418            );
419        }
420        if cur > offset || cur + self.buf.len() < offset {
421            return (stack, None);
422        }
423        let mut attrs = self.clone();
424        let mut last_off = cur + attrs.pos;
425        let mut missing = None;
426        while let Some(attr) = attrs.next() {
427            let Ok(attr) = attr else { break };
428            match attr {
429                TcpMetrics::AddrIpv4(val) => {
430                    if last_off == offset {
431                        stack.push(("AddrIpv4", last_off));
432                        break;
433                    }
434                }
435                TcpMetrics::AddrIpv6(val) => {
436                    if last_off == offset {
437                        stack.push(("AddrIpv6", last_off));
438                        break;
439                    }
440                }
441                TcpMetrics::Age(val) => {
442                    if last_off == offset {
443                        stack.push(("Age", last_off));
444                        break;
445                    }
446                }
447                TcpMetrics::TwTsval(val) => {
448                    if last_off == offset {
449                        stack.push(("TwTsval", last_off));
450                        break;
451                    }
452                }
453                TcpMetrics::TwTsStamp(val) => {
454                    if last_off == offset {
455                        stack.push(("TwTsStamp", last_off));
456                        break;
457                    }
458                }
459                TcpMetrics::Vals(val) => {
460                    (stack, missing) = val.lookup_attr(offset, missing_type);
461                    if !stack.is_empty() {
462                        break;
463                    }
464                }
465                TcpMetrics::FopenMss(val) => {
466                    if last_off == offset {
467                        stack.push(("FopenMss", last_off));
468                        break;
469                    }
470                }
471                TcpMetrics::FopenSynDrops(val) => {
472                    if last_off == offset {
473                        stack.push(("FopenSynDrops", last_off));
474                        break;
475                    }
476                }
477                TcpMetrics::FopenSynDropTs(val) => {
478                    if last_off == offset {
479                        stack.push(("FopenSynDropTs", last_off));
480                        break;
481                    }
482                }
483                TcpMetrics::FopenCookie(val) => {
484                    if last_off == offset {
485                        stack.push(("FopenCookie", last_off));
486                        break;
487                    }
488                }
489                TcpMetrics::SaddrIpv4(val) => {
490                    if last_off == offset {
491                        stack.push(("SaddrIpv4", last_off));
492                        break;
493                    }
494                }
495                TcpMetrics::SaddrIpv6(val) => {
496                    if last_off == offset {
497                        stack.push(("SaddrIpv6", last_off));
498                        break;
499                    }
500                }
501                TcpMetrics::Pad(val) => {
502                    if last_off == offset {
503                        stack.push(("Pad", last_off));
504                        break;
505                    }
506                }
507                _ => {}
508            };
509            last_off = cur + attrs.pos;
510        }
511        if !stack.is_empty() {
512            stack.push(("TcpMetrics", cur));
513        }
514        (stack, missing)
515    }
516}
517#[derive(Clone)]
518pub enum Metrics {
519    #[doc = "Round Trip Time (RTT), in msecs with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
520    Rtt(u32),
521    #[doc = "Round Trip Time VARiance (RTT), in msecs with 2 bits fractional\n(left-shift by 2 to get the msec value).\n"]
522    Rttvar(u32),
523    #[doc = "Slow Start THRESHold.\n"]
524    Ssthresh(u32),
525    #[doc = "Congestion Window.\n"]
526    Cwnd(u32),
527    #[doc = "Reodering metric.\n"]
528    Reodering(u32),
529    #[doc = "Round Trip Time (RTT), in usecs, with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
530    RttUs(u32),
531    #[doc = "Round Trip Time (RTT), in usecs, with 2 bits fractional (left-shift by 3\nto get the msec value).\n"]
532    RttvarUs(u32),
533}
534impl<'a> IterableMetrics<'a> {
535    #[doc = "Round Trip Time (RTT), in msecs with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
536    pub fn get_rtt(&self) -> Result<u32, ErrorContext> {
537        let mut iter = self.clone();
538        iter.pos = 0;
539        for attr in iter {
540            if let Ok(Metrics::Rtt(val)) = attr {
541                return Ok(val);
542            }
543        }
544        Err(ErrorContext::new_missing(
545            "Metrics",
546            "Rtt",
547            self.orig_loc,
548            self.buf.as_ptr() as usize,
549        ))
550    }
551    #[doc = "Round Trip Time VARiance (RTT), in msecs with 2 bits fractional\n(left-shift by 2 to get the msec value).\n"]
552    pub fn get_rttvar(&self) -> Result<u32, ErrorContext> {
553        let mut iter = self.clone();
554        iter.pos = 0;
555        for attr in iter {
556            if let Ok(Metrics::Rttvar(val)) = attr {
557                return Ok(val);
558            }
559        }
560        Err(ErrorContext::new_missing(
561            "Metrics",
562            "Rttvar",
563            self.orig_loc,
564            self.buf.as_ptr() as usize,
565        ))
566    }
567    #[doc = "Slow Start THRESHold.\n"]
568    pub fn get_ssthresh(&self) -> Result<u32, ErrorContext> {
569        let mut iter = self.clone();
570        iter.pos = 0;
571        for attr in iter {
572            if let Ok(Metrics::Ssthresh(val)) = attr {
573                return Ok(val);
574            }
575        }
576        Err(ErrorContext::new_missing(
577            "Metrics",
578            "Ssthresh",
579            self.orig_loc,
580            self.buf.as_ptr() as usize,
581        ))
582    }
583    #[doc = "Congestion Window.\n"]
584    pub fn get_cwnd(&self) -> Result<u32, ErrorContext> {
585        let mut iter = self.clone();
586        iter.pos = 0;
587        for attr in iter {
588            if let Ok(Metrics::Cwnd(val)) = attr {
589                return Ok(val);
590            }
591        }
592        Err(ErrorContext::new_missing(
593            "Metrics",
594            "Cwnd",
595            self.orig_loc,
596            self.buf.as_ptr() as usize,
597        ))
598    }
599    #[doc = "Reodering metric.\n"]
600    pub fn get_reodering(&self) -> Result<u32, ErrorContext> {
601        let mut iter = self.clone();
602        iter.pos = 0;
603        for attr in iter {
604            if let Ok(Metrics::Reodering(val)) = attr {
605                return Ok(val);
606            }
607        }
608        Err(ErrorContext::new_missing(
609            "Metrics",
610            "Reodering",
611            self.orig_loc,
612            self.buf.as_ptr() as usize,
613        ))
614    }
615    #[doc = "Round Trip Time (RTT), in usecs, with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
616    pub fn get_rtt_us(&self) -> Result<u32, ErrorContext> {
617        let mut iter = self.clone();
618        iter.pos = 0;
619        for attr in iter {
620            if let Ok(Metrics::RttUs(val)) = attr {
621                return Ok(val);
622            }
623        }
624        Err(ErrorContext::new_missing(
625            "Metrics",
626            "RttUs",
627            self.orig_loc,
628            self.buf.as_ptr() as usize,
629        ))
630    }
631    #[doc = "Round Trip Time (RTT), in usecs, with 2 bits fractional (left-shift by 3\nto get the msec value).\n"]
632    pub fn get_rttvar_us(&self) -> Result<u32, ErrorContext> {
633        let mut iter = self.clone();
634        iter.pos = 0;
635        for attr in iter {
636            if let Ok(Metrics::RttvarUs(val)) = attr {
637                return Ok(val);
638            }
639        }
640        Err(ErrorContext::new_missing(
641            "Metrics",
642            "RttvarUs",
643            self.orig_loc,
644            self.buf.as_ptr() as usize,
645        ))
646    }
647}
648impl Metrics {
649    pub fn new<'a>(buf: &'a [u8]) -> IterableMetrics<'a> {
650        IterableMetrics::with_loc(buf, buf.as_ptr() as usize)
651    }
652    fn attr_from_type(r#type: u16) -> Option<&'static str> {
653        let res = match r#type {
654            1u16 => "Rtt",
655            2u16 => "Rttvar",
656            3u16 => "Ssthresh",
657            4u16 => "Cwnd",
658            5u16 => "Reodering",
659            6u16 => "RttUs",
660            7u16 => "RttvarUs",
661            _ => return None,
662        };
663        Some(res)
664    }
665}
666#[derive(Clone, Copy, Default)]
667pub struct IterableMetrics<'a> {
668    buf: &'a [u8],
669    pos: usize,
670    orig_loc: usize,
671}
672impl<'a> IterableMetrics<'a> {
673    fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
674        Self {
675            buf,
676            pos: 0,
677            orig_loc,
678        }
679    }
680    pub fn get_buf(&self) -> &'a [u8] {
681        self.buf
682    }
683}
684impl<'a> Iterator for IterableMetrics<'a> {
685    type Item = Result<Metrics, ErrorContext>;
686    fn next(&mut self) -> Option<Self::Item> {
687        let mut pos;
688        let mut r#type;
689        loop {
690            pos = self.pos;
691            r#type = None;
692            if self.buf.len() == self.pos {
693                return None;
694            }
695            let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
696                self.pos = self.buf.len();
697                break;
698            };
699            r#type = Some(header.r#type);
700            let res = match header.r#type {
701                1u16 => Metrics::Rtt({
702                    let res = parse_u32(next);
703                    let Some(val) = res else { break };
704                    val
705                }),
706                2u16 => Metrics::Rttvar({
707                    let res = parse_u32(next);
708                    let Some(val) = res else { break };
709                    val
710                }),
711                3u16 => Metrics::Ssthresh({
712                    let res = parse_u32(next);
713                    let Some(val) = res else { break };
714                    val
715                }),
716                4u16 => Metrics::Cwnd({
717                    let res = parse_u32(next);
718                    let Some(val) = res else { break };
719                    val
720                }),
721                5u16 => Metrics::Reodering({
722                    let res = parse_u32(next);
723                    let Some(val) = res else { break };
724                    val
725                }),
726                6u16 => Metrics::RttUs({
727                    let res = parse_u32(next);
728                    let Some(val) = res else { break };
729                    val
730                }),
731                7u16 => Metrics::RttvarUs({
732                    let res = parse_u32(next);
733                    let Some(val) = res else { break };
734                    val
735                }),
736                n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
737                n => continue,
738            };
739            return Some(Ok(res));
740        }
741        Some(Err(ErrorContext::new(
742            "Metrics",
743            r#type.and_then(|t| Metrics::attr_from_type(t)),
744            self.orig_loc,
745            self.buf.as_ptr().wrapping_add(pos) as usize,
746        )))
747    }
748}
749impl std::fmt::Debug for IterableMetrics<'_> {
750    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
751        let mut fmt = f.debug_struct("Metrics");
752        for attr in self.clone() {
753            let attr = match attr {
754                Ok(a) => a,
755                Err(err) => {
756                    fmt.finish()?;
757                    f.write_str("Err(")?;
758                    err.fmt(f)?;
759                    return f.write_str(")");
760                }
761            };
762            match attr {
763                Metrics::Rtt(val) => fmt.field("Rtt", &val),
764                Metrics::Rttvar(val) => fmt.field("Rttvar", &val),
765                Metrics::Ssthresh(val) => fmt.field("Ssthresh", &val),
766                Metrics::Cwnd(val) => fmt.field("Cwnd", &val),
767                Metrics::Reodering(val) => fmt.field("Reodering", &val),
768                Metrics::RttUs(val) => fmt.field("RttUs", &val),
769                Metrics::RttvarUs(val) => fmt.field("RttvarUs", &val),
770            };
771        }
772        fmt.finish()
773    }
774}
775impl IterableMetrics<'_> {
776    pub fn lookup_attr(
777        &self,
778        offset: usize,
779        missing_type: Option<u16>,
780    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
781        let mut stack = Vec::new();
782        let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
783        if missing_type.is_some() && cur == offset {
784            stack.push(("Metrics", offset));
785            return (stack, missing_type.and_then(|t| Metrics::attr_from_type(t)));
786        }
787        if cur > offset || cur + self.buf.len() < offset {
788            return (stack, None);
789        }
790        let mut attrs = self.clone();
791        let mut last_off = cur + attrs.pos;
792        while let Some(attr) = attrs.next() {
793            let Ok(attr) = attr else { break };
794            match attr {
795                Metrics::Rtt(val) => {
796                    if last_off == offset {
797                        stack.push(("Rtt", last_off));
798                        break;
799                    }
800                }
801                Metrics::Rttvar(val) => {
802                    if last_off == offset {
803                        stack.push(("Rttvar", last_off));
804                        break;
805                    }
806                }
807                Metrics::Ssthresh(val) => {
808                    if last_off == offset {
809                        stack.push(("Ssthresh", last_off));
810                        break;
811                    }
812                }
813                Metrics::Cwnd(val) => {
814                    if last_off == offset {
815                        stack.push(("Cwnd", last_off));
816                        break;
817                    }
818                }
819                Metrics::Reodering(val) => {
820                    if last_off == offset {
821                        stack.push(("Reodering", last_off));
822                        break;
823                    }
824                }
825                Metrics::RttUs(val) => {
826                    if last_off == offset {
827                        stack.push(("RttUs", last_off));
828                        break;
829                    }
830                }
831                Metrics::RttvarUs(val) => {
832                    if last_off == offset {
833                        stack.push(("RttvarUs", last_off));
834                        break;
835                    }
836                }
837                _ => {}
838            };
839            last_off = cur + attrs.pos;
840        }
841        if !stack.is_empty() {
842            stack.push(("Metrics", cur));
843        }
844        (stack, None)
845    }
846}
847pub struct PushTcpMetrics<Prev: Pusher> {
848    pub(crate) prev: Option<Prev>,
849    pub(crate) header_offset: Option<usize>,
850}
851impl<Prev: Pusher> Pusher for PushTcpMetrics<Prev> {
852    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
853        self.prev.as_mut().unwrap().as_vec_mut()
854    }
855    fn as_vec(&self) -> &Vec<u8> {
856        self.prev.as_ref().unwrap().as_vec()
857    }
858}
859impl<Prev: Pusher> PushTcpMetrics<Prev> {
860    pub fn new(prev: Prev) -> Self {
861        Self {
862            prev: Some(prev),
863            header_offset: None,
864        }
865    }
866    pub fn end_nested(mut self) -> Prev {
867        let mut prev = self.prev.take().unwrap();
868        if let Some(header_offset) = &self.header_offset {
869            finalize_nested_header(prev.as_vec_mut(), *header_offset);
870        }
871        prev
872    }
873    pub fn push_addr_ipv4(mut self, value: std::net::Ipv4Addr) -> Self {
874        push_header(self.as_vec_mut(), 1u16, 4 as u16);
875        self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
876        self
877    }
878    pub fn push_addr_ipv6(mut self, value: std::net::Ipv6Addr) -> Self {
879        push_header(self.as_vec_mut(), 2u16, 16 as u16);
880        self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
881        self
882    }
883    pub fn push_age(mut self, value: u64) -> Self {
884        push_header(self.as_vec_mut(), 3u16, 8 as u16);
885        self.as_vec_mut().extend(value.to_ne_bytes());
886        self
887    }
888    #[doc = "unused\n"]
889    pub fn push_tw_tsval(mut self, value: u32) -> Self {
890        push_header(self.as_vec_mut(), 4u16, 4 as u16);
891        self.as_vec_mut().extend(value.to_ne_bytes());
892        self
893    }
894    #[doc = "unused\n"]
895    pub fn push_tw_ts_stamp(mut self, value: i32) -> Self {
896        push_header(self.as_vec_mut(), 5u16, 4 as u16);
897        self.as_vec_mut().extend(value.to_ne_bytes());
898        self
899    }
900    pub fn nested_vals(mut self) -> PushMetrics<Self> {
901        let header_offset = push_nested_header(self.as_vec_mut(), 6u16);
902        PushMetrics {
903            prev: Some(self),
904            header_offset: Some(header_offset),
905        }
906    }
907    pub fn push_fopen_mss(mut self, value: u16) -> Self {
908        push_header(self.as_vec_mut(), 7u16, 2 as u16);
909        self.as_vec_mut().extend(value.to_ne_bytes());
910        self
911    }
912    pub fn push_fopen_syn_drops(mut self, value: u16) -> Self {
913        push_header(self.as_vec_mut(), 8u16, 2 as u16);
914        self.as_vec_mut().extend(value.to_ne_bytes());
915        self
916    }
917    pub fn push_fopen_syn_drop_ts(mut self, value: u64) -> Self {
918        push_header(self.as_vec_mut(), 9u16, 8 as u16);
919        self.as_vec_mut().extend(value.to_ne_bytes());
920        self
921    }
922    pub fn push_fopen_cookie(mut self, value: &[u8]) -> Self {
923        push_header(self.as_vec_mut(), 10u16, value.len() as u16);
924        self.as_vec_mut().extend(value);
925        self
926    }
927    pub fn push_saddr_ipv4(mut self, value: std::net::Ipv4Addr) -> Self {
928        push_header(self.as_vec_mut(), 11u16, 4 as u16);
929        self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
930        self
931    }
932    pub fn push_saddr_ipv6(mut self, value: std::net::Ipv6Addr) -> Self {
933        push_header(self.as_vec_mut(), 12u16, 16 as u16);
934        self.as_vec_mut().extend(&value.to_bits().to_be_bytes());
935        self
936    }
937    pub fn push_pad(mut self, value: &[u8]) -> Self {
938        push_header(self.as_vec_mut(), 13u16, value.len() as u16);
939        self.as_vec_mut().extend(value);
940        self
941    }
942}
943impl<Prev: Pusher> Drop for PushTcpMetrics<Prev> {
944    fn drop(&mut self) {
945        if let Some(prev) = &mut self.prev {
946            if let Some(header_offset) = &self.header_offset {
947                finalize_nested_header(prev.as_vec_mut(), *header_offset);
948            }
949        }
950    }
951}
952pub struct PushMetrics<Prev: Pusher> {
953    pub(crate) prev: Option<Prev>,
954    pub(crate) header_offset: Option<usize>,
955}
956impl<Prev: Pusher> Pusher for PushMetrics<Prev> {
957    fn as_vec_mut(&mut self) -> &mut Vec<u8> {
958        self.prev.as_mut().unwrap().as_vec_mut()
959    }
960    fn as_vec(&self) -> &Vec<u8> {
961        self.prev.as_ref().unwrap().as_vec()
962    }
963}
964impl<Prev: Pusher> PushMetrics<Prev> {
965    pub fn new(prev: Prev) -> Self {
966        Self {
967            prev: Some(prev),
968            header_offset: None,
969        }
970    }
971    pub fn end_nested(mut self) -> Prev {
972        let mut prev = self.prev.take().unwrap();
973        if let Some(header_offset) = &self.header_offset {
974            finalize_nested_header(prev.as_vec_mut(), *header_offset);
975        }
976        prev
977    }
978    #[doc = "Round Trip Time (RTT), in msecs with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
979    pub fn push_rtt(mut self, value: u32) -> Self {
980        push_header(self.as_vec_mut(), 1u16, 4 as u16);
981        self.as_vec_mut().extend(value.to_ne_bytes());
982        self
983    }
984    #[doc = "Round Trip Time VARiance (RTT), in msecs with 2 bits fractional\n(left-shift by 2 to get the msec value).\n"]
985    pub fn push_rttvar(mut self, value: u32) -> Self {
986        push_header(self.as_vec_mut(), 2u16, 4 as u16);
987        self.as_vec_mut().extend(value.to_ne_bytes());
988        self
989    }
990    #[doc = "Slow Start THRESHold.\n"]
991    pub fn push_ssthresh(mut self, value: u32) -> Self {
992        push_header(self.as_vec_mut(), 3u16, 4 as u16);
993        self.as_vec_mut().extend(value.to_ne_bytes());
994        self
995    }
996    #[doc = "Congestion Window.\n"]
997    pub fn push_cwnd(mut self, value: u32) -> Self {
998        push_header(self.as_vec_mut(), 4u16, 4 as u16);
999        self.as_vec_mut().extend(value.to_ne_bytes());
1000        self
1001    }
1002    #[doc = "Reodering metric.\n"]
1003    pub fn push_reodering(mut self, value: u32) -> Self {
1004        push_header(self.as_vec_mut(), 5u16, 4 as u16);
1005        self.as_vec_mut().extend(value.to_ne_bytes());
1006        self
1007    }
1008    #[doc = "Round Trip Time (RTT), in usecs, with 3 bits fractional (left-shift by 3\nto get the msec value).\n"]
1009    pub fn push_rtt_us(mut self, value: u32) -> Self {
1010        push_header(self.as_vec_mut(), 6u16, 4 as u16);
1011        self.as_vec_mut().extend(value.to_ne_bytes());
1012        self
1013    }
1014    #[doc = "Round Trip Time (RTT), in usecs, with 2 bits fractional (left-shift by 3\nto get the msec value).\n"]
1015    pub fn push_rttvar_us(mut self, value: u32) -> Self {
1016        push_header(self.as_vec_mut(), 7u16, 4 as u16);
1017        self.as_vec_mut().extend(value.to_ne_bytes());
1018        self
1019    }
1020}
1021impl<Prev: Pusher> Drop for PushMetrics<Prev> {
1022    fn drop(&mut self) {
1023        if let Some(prev) = &mut self.prev {
1024            if let Some(header_offset) = &self.header_offset {
1025                finalize_nested_header(prev.as_vec_mut(), *header_offset);
1026            }
1027        }
1028    }
1029}
1030#[doc = "Retrieve metrics.\n\nReply attributes:\n- [.get_addr_ipv4()](IterableTcpMetrics::get_addr_ipv4)\n- [.get_addr_ipv6()](IterableTcpMetrics::get_addr_ipv6)\n- [.get_age()](IterableTcpMetrics::get_age)\n- [.get_vals()](IterableTcpMetrics::get_vals)\n- [.get_fopen_mss()](IterableTcpMetrics::get_fopen_mss)\n- [.get_fopen_syn_drops()](IterableTcpMetrics::get_fopen_syn_drops)\n- [.get_fopen_syn_drop_ts()](IterableTcpMetrics::get_fopen_syn_drop_ts)\n- [.get_fopen_cookie()](IterableTcpMetrics::get_fopen_cookie)\n- [.get_saddr_ipv4()](IterableTcpMetrics::get_saddr_ipv4)\n- [.get_saddr_ipv6()](IterableTcpMetrics::get_saddr_ipv6)\n\n"]
1031#[derive(Debug)]
1032pub struct OpGetDump<'r> {
1033    request: Request<'r>,
1034}
1035impl<'r> OpGetDump<'r> {
1036    pub fn new(mut request: Request<'r>) -> Self {
1037        Self::write_header(request.buf_mut());
1038        Self {
1039            request: request.set_dump(),
1040        }
1041    }
1042    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTcpMetrics<&'buf mut Vec<u8>> {
1043        Self::write_header(buf);
1044        PushTcpMetrics::new(buf)
1045    }
1046    pub fn encode(&mut self) -> PushTcpMetrics<&mut Vec<u8>> {
1047        PushTcpMetrics::new(self.request.buf_mut())
1048    }
1049    pub fn into_encoder(self) -> PushTcpMetrics<RequestBuf<'r>> {
1050        PushTcpMetrics::new(self.request.buf)
1051    }
1052    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTcpMetrics<'a> {
1053        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1054        IterableTcpMetrics::with_loc(attrs, buf.as_ptr() as usize)
1055    }
1056    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1057        let mut header = BuiltinNfgenmsg::new();
1058        header.cmd = 1u8;
1059        header.version = 1u8;
1060        prev.as_vec_mut().extend(header.as_slice());
1061    }
1062}
1063impl NetlinkRequest for OpGetDump<'_> {
1064    fn protocol(&self) -> Protocol {
1065        Protocol::Generic("tcp_metrics".as_bytes())
1066    }
1067    fn flags(&self) -> u16 {
1068        self.request.flags
1069    }
1070    fn payload(&self) -> &[u8] {
1071        self.request.buf()
1072    }
1073    type ReplyType<'buf> = IterableTcpMetrics<'buf>;
1074    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1075        Self::decode_request(buf)
1076    }
1077    fn lookup(
1078        buf: &[u8],
1079        offset: usize,
1080        missing_type: Option<u16>,
1081    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1082        Self::decode_request(buf).lookup_attr(offset, missing_type)
1083    }
1084}
1085#[doc = "Retrieve metrics.\n\nRequest attributes:\n- [.push_addr_ipv4()](PushTcpMetrics::push_addr_ipv4)\n- [.push_addr_ipv6()](PushTcpMetrics::push_addr_ipv6)\n- [.push_saddr_ipv4()](PushTcpMetrics::push_saddr_ipv4)\n- [.push_saddr_ipv6()](PushTcpMetrics::push_saddr_ipv6)\n\nReply attributes:\n- [.get_addr_ipv4()](IterableTcpMetrics::get_addr_ipv4)\n- [.get_addr_ipv6()](IterableTcpMetrics::get_addr_ipv6)\n- [.get_age()](IterableTcpMetrics::get_age)\n- [.get_vals()](IterableTcpMetrics::get_vals)\n- [.get_fopen_mss()](IterableTcpMetrics::get_fopen_mss)\n- [.get_fopen_syn_drops()](IterableTcpMetrics::get_fopen_syn_drops)\n- [.get_fopen_syn_drop_ts()](IterableTcpMetrics::get_fopen_syn_drop_ts)\n- [.get_fopen_cookie()](IterableTcpMetrics::get_fopen_cookie)\n- [.get_saddr_ipv4()](IterableTcpMetrics::get_saddr_ipv4)\n- [.get_saddr_ipv6()](IterableTcpMetrics::get_saddr_ipv6)\n\n"]
1086#[derive(Debug)]
1087pub struct OpGetDo<'r> {
1088    request: Request<'r>,
1089}
1090impl<'r> OpGetDo<'r> {
1091    pub fn new(mut request: Request<'r>) -> Self {
1092        Self::write_header(request.buf_mut());
1093        Self { request: request }
1094    }
1095    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTcpMetrics<&'buf mut Vec<u8>> {
1096        Self::write_header(buf);
1097        PushTcpMetrics::new(buf)
1098    }
1099    pub fn encode(&mut self) -> PushTcpMetrics<&mut Vec<u8>> {
1100        PushTcpMetrics::new(self.request.buf_mut())
1101    }
1102    pub fn into_encoder(self) -> PushTcpMetrics<RequestBuf<'r>> {
1103        PushTcpMetrics::new(self.request.buf)
1104    }
1105    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTcpMetrics<'a> {
1106        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1107        IterableTcpMetrics::with_loc(attrs, buf.as_ptr() as usize)
1108    }
1109    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1110        let mut header = BuiltinNfgenmsg::new();
1111        header.cmd = 1u8;
1112        header.version = 1u8;
1113        prev.as_vec_mut().extend(header.as_slice());
1114    }
1115}
1116impl NetlinkRequest for OpGetDo<'_> {
1117    fn protocol(&self) -> Protocol {
1118        Protocol::Generic("tcp_metrics".as_bytes())
1119    }
1120    fn flags(&self) -> u16 {
1121        self.request.flags
1122    }
1123    fn payload(&self) -> &[u8] {
1124        self.request.buf()
1125    }
1126    type ReplyType<'buf> = IterableTcpMetrics<'buf>;
1127    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1128        Self::decode_request(buf)
1129    }
1130    fn lookup(
1131        buf: &[u8],
1132        offset: usize,
1133        missing_type: Option<u16>,
1134    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1135        Self::decode_request(buf).lookup_attr(offset, missing_type)
1136    }
1137}
1138#[doc = "Delete metrics.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_addr_ipv4()](PushTcpMetrics::push_addr_ipv4)\n- [.push_addr_ipv6()](PushTcpMetrics::push_addr_ipv6)\n- [.push_saddr_ipv4()](PushTcpMetrics::push_saddr_ipv4)\n- [.push_saddr_ipv6()](PushTcpMetrics::push_saddr_ipv6)\n\n"]
1139#[derive(Debug)]
1140pub struct OpDelDo<'r> {
1141    request: Request<'r>,
1142}
1143impl<'r> OpDelDo<'r> {
1144    pub fn new(mut request: Request<'r>) -> Self {
1145        Self::write_header(request.buf_mut());
1146        Self { request: request }
1147    }
1148    pub fn encode_request<'buf>(buf: &'buf mut Vec<u8>) -> PushTcpMetrics<&'buf mut Vec<u8>> {
1149        Self::write_header(buf);
1150        PushTcpMetrics::new(buf)
1151    }
1152    pub fn encode(&mut self) -> PushTcpMetrics<&mut Vec<u8>> {
1153        PushTcpMetrics::new(self.request.buf_mut())
1154    }
1155    pub fn into_encoder(self) -> PushTcpMetrics<RequestBuf<'r>> {
1156        PushTcpMetrics::new(self.request.buf)
1157    }
1158    pub fn decode_request<'a>(buf: &'a [u8]) -> IterableTcpMetrics<'a> {
1159        let (_header, attrs) = buf.split_at(buf.len().min(BuiltinNfgenmsg::len()));
1160        IterableTcpMetrics::with_loc(attrs, buf.as_ptr() as usize)
1161    }
1162    fn write_header<Prev: Pusher>(prev: &mut Prev) {
1163        let mut header = BuiltinNfgenmsg::new();
1164        header.cmd = 2u8;
1165        header.version = 1u8;
1166        prev.as_vec_mut().extend(header.as_slice());
1167    }
1168}
1169impl NetlinkRequest for OpDelDo<'_> {
1170    fn protocol(&self) -> Protocol {
1171        Protocol::Generic("tcp_metrics".as_bytes())
1172    }
1173    fn flags(&self) -> u16 {
1174        self.request.flags
1175    }
1176    fn payload(&self) -> &[u8] {
1177        self.request.buf()
1178    }
1179    type ReplyType<'buf> = IterableTcpMetrics<'buf>;
1180    fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
1181        Self::decode_request(buf)
1182    }
1183    fn lookup(
1184        buf: &[u8],
1185        offset: usize,
1186        missing_type: Option<u16>,
1187    ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
1188        Self::decode_request(buf).lookup_attr(offset, missing_type)
1189    }
1190}
1191use crate::traits::LookupFn;
1192use crate::utils::RequestBuf;
1193#[derive(Debug)]
1194pub struct Request<'buf> {
1195    buf: RequestBuf<'buf>,
1196    flags: u16,
1197    writeback: Option<&'buf mut Option<RequestInfo>>,
1198}
1199#[allow(unused)]
1200#[derive(Debug, Clone)]
1201pub struct RequestInfo {
1202    protocol: Protocol,
1203    flags: u16,
1204    name: &'static str,
1205    lookup: LookupFn,
1206}
1207impl Request<'static> {
1208    pub fn new() -> Self {
1209        Self::new_from_buf(Vec::new())
1210    }
1211    pub fn new_from_buf(buf: Vec<u8>) -> Self {
1212        Self {
1213            flags: 0,
1214            buf: RequestBuf::Own(buf),
1215            writeback: None,
1216        }
1217    }
1218    pub fn into_buf(self) -> Vec<u8> {
1219        match self.buf {
1220            RequestBuf::Own(buf) => buf,
1221            _ => unreachable!(),
1222        }
1223    }
1224}
1225impl<'buf> Request<'buf> {
1226    pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
1227        buf.clear();
1228        Self::new_extend(buf)
1229    }
1230    pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
1231        Self {
1232            flags: 0,
1233            buf: RequestBuf::Ref(buf),
1234            writeback: None,
1235        }
1236    }
1237    fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
1238        let Some(writeback) = &mut self.writeback else {
1239            return;
1240        };
1241        **writeback = Some(RequestInfo {
1242            protocol,
1243            flags: self.flags,
1244            name,
1245            lookup,
1246        })
1247    }
1248    pub fn buf(&self) -> &Vec<u8> {
1249        self.buf.buf()
1250    }
1251    pub fn buf_mut(&mut self) -> &mut Vec<u8> {
1252        self.buf.buf_mut()
1253    }
1254    #[doc = "Set `NLM_F_CREATE` flag"]
1255    pub fn set_create(mut self) -> Self {
1256        self.flags |= consts::NLM_F_CREATE as u16;
1257        self
1258    }
1259    #[doc = "Set `NLM_F_EXCL` flag"]
1260    pub fn set_excl(mut self) -> Self {
1261        self.flags |= consts::NLM_F_EXCL as u16;
1262        self
1263    }
1264    #[doc = "Set `NLM_F_REPLACE` flag"]
1265    pub fn set_replace(mut self) -> Self {
1266        self.flags |= consts::NLM_F_REPLACE as u16;
1267        self
1268    }
1269    #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
1270    pub fn set_change(self) -> Self {
1271        self.set_create().set_replace()
1272    }
1273    #[doc = "Set `NLM_F_APPEND` flag"]
1274    pub fn set_append(mut self) -> Self {
1275        self.flags |= consts::NLM_F_APPEND as u16;
1276        self
1277    }
1278    #[doc = "Set `self.flags |= flags`"]
1279    pub fn set_flags(mut self, flags: u16) -> Self {
1280        self.flags |= flags;
1281        self
1282    }
1283    #[doc = "Set `self.flags ^= self.flags & flags`"]
1284    pub fn unset_flags(mut self, flags: u16) -> Self {
1285        self.flags ^= self.flags & flags;
1286        self
1287    }
1288    #[doc = "Set `NLM_F_DUMP` flag"]
1289    fn set_dump(mut self) -> Self {
1290        self.flags |= consts::NLM_F_DUMP as u16;
1291        self
1292    }
1293    #[doc = "Retrieve metrics.\n\nReply attributes:\n- [.get_addr_ipv4()](IterableTcpMetrics::get_addr_ipv4)\n- [.get_addr_ipv6()](IterableTcpMetrics::get_addr_ipv6)\n- [.get_age()](IterableTcpMetrics::get_age)\n- [.get_vals()](IterableTcpMetrics::get_vals)\n- [.get_fopen_mss()](IterableTcpMetrics::get_fopen_mss)\n- [.get_fopen_syn_drops()](IterableTcpMetrics::get_fopen_syn_drops)\n- [.get_fopen_syn_drop_ts()](IterableTcpMetrics::get_fopen_syn_drop_ts)\n- [.get_fopen_cookie()](IterableTcpMetrics::get_fopen_cookie)\n- [.get_saddr_ipv4()](IterableTcpMetrics::get_saddr_ipv4)\n- [.get_saddr_ipv6()](IterableTcpMetrics::get_saddr_ipv6)\n\n"]
1294    pub fn op_get_dump(self) -> OpGetDump<'buf> {
1295        let mut res = OpGetDump::new(self);
1296        res.request
1297            .do_writeback(res.protocol(), "op-get-dump", OpGetDump::lookup);
1298        res
1299    }
1300    #[doc = "Retrieve metrics.\n\nRequest attributes:\n- [.push_addr_ipv4()](PushTcpMetrics::push_addr_ipv4)\n- [.push_addr_ipv6()](PushTcpMetrics::push_addr_ipv6)\n- [.push_saddr_ipv4()](PushTcpMetrics::push_saddr_ipv4)\n- [.push_saddr_ipv6()](PushTcpMetrics::push_saddr_ipv6)\n\nReply attributes:\n- [.get_addr_ipv4()](IterableTcpMetrics::get_addr_ipv4)\n- [.get_addr_ipv6()](IterableTcpMetrics::get_addr_ipv6)\n- [.get_age()](IterableTcpMetrics::get_age)\n- [.get_vals()](IterableTcpMetrics::get_vals)\n- [.get_fopen_mss()](IterableTcpMetrics::get_fopen_mss)\n- [.get_fopen_syn_drops()](IterableTcpMetrics::get_fopen_syn_drops)\n- [.get_fopen_syn_drop_ts()](IterableTcpMetrics::get_fopen_syn_drop_ts)\n- [.get_fopen_cookie()](IterableTcpMetrics::get_fopen_cookie)\n- [.get_saddr_ipv4()](IterableTcpMetrics::get_saddr_ipv4)\n- [.get_saddr_ipv6()](IterableTcpMetrics::get_saddr_ipv6)\n\n"]
1301    pub fn op_get_do(self) -> OpGetDo<'buf> {
1302        let mut res = OpGetDo::new(self);
1303        res.request
1304            .do_writeback(res.protocol(), "op-get-do", OpGetDo::lookup);
1305        res
1306    }
1307    #[doc = "Delete metrics.\n\nFlags: admin-perm\n\nRequest attributes:\n- [.push_addr_ipv4()](PushTcpMetrics::push_addr_ipv4)\n- [.push_addr_ipv6()](PushTcpMetrics::push_addr_ipv6)\n- [.push_saddr_ipv4()](PushTcpMetrics::push_saddr_ipv4)\n- [.push_saddr_ipv6()](PushTcpMetrics::push_saddr_ipv6)\n\n"]
1308    pub fn op_del_do(self) -> OpDelDo<'buf> {
1309        let mut res = OpDelDo::new(self);
1310        res.request
1311            .do_writeback(res.protocol(), "op-del-do", OpDelDo::lookup);
1312        res
1313    }
1314}
1315#[cfg(test)]
1316mod generated_tests {
1317    use super::*;
1318    #[test]
1319    fn tests() {
1320        let _ = IterableTcpMetrics::get_addr_ipv4;
1321        let _ = IterableTcpMetrics::get_addr_ipv6;
1322        let _ = IterableTcpMetrics::get_age;
1323        let _ = IterableTcpMetrics::get_fopen_cookie;
1324        let _ = IterableTcpMetrics::get_fopen_mss;
1325        let _ = IterableTcpMetrics::get_fopen_syn_drop_ts;
1326        let _ = IterableTcpMetrics::get_fopen_syn_drops;
1327        let _ = IterableTcpMetrics::get_saddr_ipv4;
1328        let _ = IterableTcpMetrics::get_saddr_ipv6;
1329        let _ = IterableTcpMetrics::get_vals;
1330        let _ = PushTcpMetrics::<&mut Vec<u8>>::push_addr_ipv4;
1331        let _ = PushTcpMetrics::<&mut Vec<u8>>::push_addr_ipv6;
1332        let _ = PushTcpMetrics::<&mut Vec<u8>>::push_saddr_ipv4;
1333        let _ = PushTcpMetrics::<&mut Vec<u8>>::push_saddr_ipv6;
1334    }
1335}