netlink_packet_route/rtnl/route/nlas/
metrics.rs1use 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}