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