netlink_packet_route/rtnl/route/nlas/
metrics.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5use std::mem::size_of;
6
7use crate::constants::*;
8
9use netlink_packet_utils::{
10    nla::{DefaultNla, Nla, NlaBuffer},
11    parsers::parse_u32,
12    traits::Parseable,
13    DecodeError,
14};
15
16#[derive(Debug, PartialEq, Eq, Clone)]
17#[non_exhaustive]
18pub enum Metrics {
19    Unspec(Vec<u8>),
20    Lock(u32),
21    Mtu(u32),
22    Window(u32),
23    Rtt(u32),
24    RttVar(u32),
25    SsThresh(u32),
26    Cwnd(u32),
27    Advmss(u32),
28    Reordering(u32),
29    Hoplimit(u32),
30    InitCwnd(u32),
31    Features(u32),
32    RtoMin(u32),
33    InitRwnd(u32),
34    QuickAck(u32),
35    CcAlgo(u32),
36    FastopenNoCookie(u32),
37    Other(DefaultNla),
38}
39
40impl Nla for Metrics {
41    #[rustfmt::skip]
42    fn value_len(&self) -> usize {
43        use self::Metrics::*;
44        match *self {
45            Unspec(ref bytes) => bytes.len(),
46            Lock(_)
47                | Mtu(_)
48                | Window(_)
49                | Rtt(_)
50                | RttVar(_)
51                | SsThresh(_)
52                | Cwnd(_)
53                | Advmss(_)
54                | Reordering(_)
55                | Hoplimit(_)
56                | InitCwnd(_)
57                | Features(_)
58                | RtoMin(_)
59                | InitRwnd(_)
60                | QuickAck(_)
61                | CcAlgo(_)
62                | FastopenNoCookie(_)
63                => size_of::<u32>(),
64            Other(ref attr) => attr.value_len(),
65        }
66    }
67
68    #[rustfmt::skip]
69    fn emit_value(&self, buffer: &mut [u8]) {
70        use self::Metrics::*;
71        match *self {
72            Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
73
74            Lock(value)
75                | Mtu(value)
76                | Window(value)
77                | Rtt(value)
78                | RttVar(value)
79                | SsThresh(value)
80                | Cwnd(value)
81                | Advmss(value)
82                | Reordering(value)
83                | Hoplimit(value)
84                | InitCwnd(value)
85                | Features(value)
86                | RtoMin(value)
87                | InitRwnd(value)
88                | QuickAck(value)
89                | CcAlgo(value)
90                | FastopenNoCookie(value)
91                => NativeEndian::write_u32(buffer, value),
92
93            Other(ref attr) => attr.emit_value(buffer),
94        }
95    }
96
97    fn kind(&self) -> u16 {
98        use self::Metrics::*;
99        match *self {
100            Unspec(_) => RTAX_UNSPEC,
101            Lock(_) => RTAX_LOCK,
102            Mtu(_) => RTAX_MTU,
103            Window(_) => RTAX_WINDOW,
104            Rtt(_) => RTAX_RTT,
105            RttVar(_) => RTAX_RTTVAR,
106            SsThresh(_) => RTAX_SSTHRESH,
107            Cwnd(_) => RTAX_CWND,
108            Advmss(_) => RTAX_ADVMSS,
109            Reordering(_) => RTAX_REORDERING,
110            Hoplimit(_) => RTAX_HOPLIMIT,
111            InitCwnd(_) => RTAX_INITCWND,
112            Features(_) => RTAX_FEATURES,
113            RtoMin(_) => RTAX_RTO_MIN,
114            InitRwnd(_) => RTAX_INITRWND,
115            QuickAck(_) => RTAX_QUICKACK,
116            CcAlgo(_) => RTAX_CC_ALGO,
117            FastopenNoCookie(_) => RTAX_FASTOPEN_NO_COOKIE,
118            Other(ref attr) => attr.kind(),
119        }
120    }
121}
122
123impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Metrics {
124    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
125        use self::Metrics::*;
126        let payload = buf.value();
127        Ok(match buf.kind() {
128            RTAX_UNSPEC => Unspec(payload.to_vec()),
129            RTAX_LOCK => {
130                Lock(parse_u32(payload).context("invalid RTAX_LOCK value")?)
131            }
132            RTAX_MTU => {
133                Mtu(parse_u32(payload).context("invalid RTAX_MTU value")?)
134            }
135            RTAX_WINDOW => {
136                Window(parse_u32(payload).context("invalid RTAX_WINDOW value")?)
137            }
138            RTAX_RTT => {
139                Rtt(parse_u32(payload).context("invalid RTAX_RTT value")?)
140            }
141            RTAX_RTTVAR => {
142                RttVar(parse_u32(payload).context("invalid RTAX_RTTVAR value")?)
143            }
144            RTAX_SSTHRESH => SsThresh(
145                parse_u32(payload).context("invalid RTAX_SSTHRESH value")?,
146            ),
147            RTAX_CWND => {
148                Cwnd(parse_u32(payload).context("invalid RTAX_CWND value")?)
149            }
150            RTAX_ADVMSS => {
151                Advmss(parse_u32(payload).context("invalid RTAX_ADVMSS value")?)
152            }
153            RTAX_REORDERING => Reordering(
154                parse_u32(payload).context("invalid RTAX_REORDERING value")?,
155            ),
156            RTAX_HOPLIMIT => Hoplimit(
157                parse_u32(payload).context("invalid RTAX_HOPLIMIT value")?,
158            ),
159            RTAX_INITCWND => InitCwnd(
160                parse_u32(payload).context("invalid RTAX_INITCWND value")?,
161            ),
162            RTAX_FEATURES => Features(
163                parse_u32(payload).context("invalid RTAX_FEATURES value")?,
164            ),
165            RTAX_RTO_MIN => RtoMin(
166                parse_u32(payload).context("invalid RTAX_RTO_MIN value")?,
167            ),
168            RTAX_INITRWND => InitRwnd(
169                parse_u32(payload).context("invalid RTAX_INITRWND value")?,
170            ),
171            RTAX_QUICKACK => QuickAck(
172                parse_u32(payload).context("invalid RTAX_QUICKACK value")?,
173            ),
174            RTAX_CC_ALGO => CcAlgo(
175                parse_u32(payload).context("invalid RTAX_CC_ALGO value")?,
176            ),
177            RTAX_FASTOPEN_NO_COOKIE => FastopenNoCookie(
178                parse_u32(payload)
179                    .context("invalid RTAX_FASTOPEN_NO_COOKIE value")?,
180            ),
181            _ => Other(
182                DefaultNla::parse(buf)
183                    .context("invalid NLA value (unknown type) value")?,
184            ),
185        })
186    }
187}