netlink_packet_route/link/link_info/
vxlan.rs1use std::net::{Ipv4Addr, Ipv6Addr};
4
5use netlink_packet_core::{
6 emit_u16_be, emit_u32, parse_u16_be, parse_u32, parse_u8, DecodeError,
7 DefaultNla, ErrorContext, Nla, NlaBuffer, Parseable,
8};
9
10const IFLA_VXLAN_ID: u16 = 1;
11const IFLA_VXLAN_GROUP: u16 = 2;
12const IFLA_VXLAN_LINK: u16 = 3;
13const IFLA_VXLAN_LOCAL: u16 = 4;
14const IFLA_VXLAN_TTL: u16 = 5;
15const IFLA_VXLAN_TOS: u16 = 6;
16const IFLA_VXLAN_LEARNING: u16 = 7;
17const IFLA_VXLAN_AGEING: u16 = 8;
18const IFLA_VXLAN_LIMIT: u16 = 9;
19const IFLA_VXLAN_PORT_RANGE: u16 = 10;
20const IFLA_VXLAN_PROXY: u16 = 11;
21const IFLA_VXLAN_RSC: u16 = 12;
22const IFLA_VXLAN_L2MISS: u16 = 13;
23const IFLA_VXLAN_L3MISS: u16 = 14;
24const IFLA_VXLAN_PORT: u16 = 15;
25const IFLA_VXLAN_GROUP6: u16 = 16;
26const IFLA_VXLAN_LOCAL6: u16 = 17;
27const IFLA_VXLAN_UDP_CSUM: u16 = 18;
28const IFLA_VXLAN_UDP_ZERO_CSUM6_TX: u16 = 19;
29const IFLA_VXLAN_UDP_ZERO_CSUM6_RX: u16 = 20;
30const IFLA_VXLAN_REMCSUM_TX: u16 = 21;
31const IFLA_VXLAN_REMCSUM_RX: u16 = 22;
32const IFLA_VXLAN_GBP: u16 = 23;
33const IFLA_VXLAN_REMCSUM_NOPARTIAL: u16 = 24;
34const IFLA_VXLAN_COLLECT_METADATA: u16 = 25;
35const IFLA_VXLAN_LABEL: u16 = 26;
36const IFLA_VXLAN_GPE: u16 = 27;
37const IFLA_VXLAN_TTL_INHERIT: u16 = 28;
38const IFLA_VXLAN_DF: u16 = 29;
39const IFLA_VXLAN_VNIFILTER: u16 = 30;
40const IFLA_VXLAN_LOCALBYPASS: u16 = 31;
41
42#[derive(Debug, PartialEq, Eq, Clone)]
43#[non_exhaustive]
44pub enum InfoVxlan {
45 Id(u32),
46 Group(Ipv4Addr),
47 Group6(Ipv6Addr),
48 Link(u32),
49 Local(Ipv4Addr),
50 Local6(Ipv6Addr),
51 Tos(u8),
52 Ttl(u8),
53 Label(u32),
54 Learning(bool),
55 Ageing(u32),
56 Limit(u32),
57 PortRange((u16, u16)),
58 Proxy(bool),
59 Rsc(bool),
60 L2Miss(bool),
61 L3Miss(bool),
62 CollectMetadata(bool),
63 Port(u16),
64 UDPCsum(bool),
65 UDPZeroCsumTX(bool),
66 UDPZeroCsumRX(bool),
67 RemCsumTX(bool),
68 RemCsumRX(bool),
69 Gbp(bool),
70 Gpe(bool),
71 RemCsumNoPartial(bool),
72 TtlInherit(bool),
73 Df(u8),
74 Vnifilter(bool),
75 Localbypass(bool),
76 Other(DefaultNla),
77}
78
79impl Nla for InfoVxlan {
80 fn value_len(&self) -> usize {
81 match self {
82 Self::Tos(_)
83 | Self::Ttl(_)
84 | Self::Learning(_)
85 | Self::Proxy(_)
86 | Self::Rsc(_)
87 | Self::L2Miss(_)
88 | Self::L3Miss(_)
89 | Self::CollectMetadata(_)
90 | Self::UDPCsum(_)
91 | Self::UDPZeroCsumTX(_)
92 | Self::UDPZeroCsumRX(_)
93 | Self::RemCsumTX(_)
94 | Self::RemCsumRX(_)
95 | Self::TtlInherit(_)
96 | Self::Df(_)
97 | Self::Vnifilter(_)
98 | Self::Localbypass(_) => 1,
99 Self::Gbp(_) | Self::Gpe(_) | Self::RemCsumNoPartial(_) => 0,
100 Self::Port(_) => 2,
101 Self::Id(_)
102 | Self::Label(_)
103 | Self::Link(_)
104 | Self::Ageing(_)
105 | Self::Limit(_)
106 | Self::PortRange(_)
107 | Self::Group(_)
108 | Self::Local(_) => 4,
109 Self::Group6(_) | Self::Local6(_) => 16,
110 Self::Other(nla) => nla.value_len(),
111 }
112 }
113
114 fn emit_value(&self, buffer: &mut [u8]) {
115 match self {
116 Self::Id(value)
117 | Self::Label(value)
118 | Self::Link(value)
119 | Self::Ageing(value)
120 | Self::Limit(value) => emit_u32(buffer, *value).unwrap(),
121 Self::Gbp(_value)
122 | Self::Gpe(_value)
123 | Self::RemCsumNoPartial(_value) => (),
124 Self::Tos(value) | Self::Ttl(value) | Self::Df(value) => {
125 buffer[0] = *value
126 }
127 Self::Vnifilter(value)
128 | Self::Localbypass(value)
129 | Self::Learning(value)
130 | Self::Proxy(value)
131 | Self::Rsc(value)
132 | Self::L2Miss(value)
133 | Self::L3Miss(value)
134 | Self::CollectMetadata(value)
135 | Self::UDPCsum(value)
136 | Self::UDPZeroCsumTX(value)
137 | Self::UDPZeroCsumRX(value)
138 | Self::RemCsumTX(value)
139 | Self::RemCsumRX(value)
140 | Self::TtlInherit(value) => buffer[0] = *value as u8,
141 Self::Group(value) | Self::Local(value) => {
142 buffer.copy_from_slice(&value.octets())
143 }
144 Self::Group6(value) | Self::Local6(value) => {
145 buffer.copy_from_slice(&value.octets())
146 }
147 Self::Port(value) => emit_u16_be(buffer, *value).unwrap(),
148 Self::PortRange(range) => {
149 emit_u16_be(buffer, range.0).unwrap();
150 emit_u16_be(&mut buffer[2..], range.1).unwrap()
151 }
152 Self::Other(nla) => nla.emit_value(buffer),
153 }
154 }
155
156 fn kind(&self) -> u16 {
157 match self {
158 Self::Id(_) => IFLA_VXLAN_ID,
159 Self::Group(_) => IFLA_VXLAN_GROUP,
160 Self::Group6(_) => IFLA_VXLAN_GROUP6,
161 Self::Link(_) => IFLA_VXLAN_LINK,
162 Self::Local(_) => IFLA_VXLAN_LOCAL,
163 Self::Local6(_) => IFLA_VXLAN_LOCAL6,
164 Self::Tos(_) => IFLA_VXLAN_TOS,
165 Self::Ttl(_) => IFLA_VXLAN_TTL,
166 Self::Label(_) => IFLA_VXLAN_LABEL,
167 Self::Learning(_) => IFLA_VXLAN_LEARNING,
168 Self::Ageing(_) => IFLA_VXLAN_AGEING,
169 Self::Limit(_) => IFLA_VXLAN_LIMIT,
170 Self::PortRange(_) => IFLA_VXLAN_PORT_RANGE,
171 Self::Proxy(_) => IFLA_VXLAN_PROXY,
172 Self::Rsc(_) => IFLA_VXLAN_RSC,
173 Self::L2Miss(_) => IFLA_VXLAN_L2MISS,
174 Self::L3Miss(_) => IFLA_VXLAN_L3MISS,
175 Self::CollectMetadata(_) => IFLA_VXLAN_COLLECT_METADATA,
176 Self::Port(_) => IFLA_VXLAN_PORT,
177 Self::UDPCsum(_) => IFLA_VXLAN_UDP_CSUM,
178 Self::UDPZeroCsumTX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
179 Self::UDPZeroCsumRX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
180 Self::RemCsumTX(_) => IFLA_VXLAN_REMCSUM_TX,
181 Self::RemCsumRX(_) => IFLA_VXLAN_REMCSUM_RX,
182 Self::Gbp(_) => IFLA_VXLAN_GBP,
183 Self::Gpe(_) => IFLA_VXLAN_GPE,
184 Self::RemCsumNoPartial(_) => IFLA_VXLAN_REMCSUM_NOPARTIAL,
185 Self::TtlInherit(_) => IFLA_VXLAN_TTL_INHERIT,
186 Self::Df(_) => IFLA_VXLAN_DF,
187 Self::Vnifilter(_) => IFLA_VXLAN_VNIFILTER,
188 Self::Localbypass(_) => IFLA_VXLAN_LOCALBYPASS,
189 Self::Other(nla) => nla.kind(),
190 }
191 }
192}
193
194impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVxlan {
195 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
196 let payload = buf.value();
197 Ok(match buf.kind() {
198 IFLA_VXLAN_ID => Self::Id(
199 parse_u32(payload).context("invalid IFLA_VXLAN_ID value")?,
200 ),
201 IFLA_VXLAN_GROUP => {
202 if payload.len() == 4 {
203 let mut data = [0u8; 4];
204 data.copy_from_slice(&payload[0..4]);
205 Self::Group(Ipv4Addr::from(data))
206 } else {
207 return Err(DecodeError::from(format!(
208 "Invalid IFLA_VXLAN_GROUP, got unexpected length of \
209 IPv4 address payload {payload:?}"
210 )));
211 }
212 }
213 IFLA_VXLAN_LOCAL => {
214 if payload.len() == 4 {
215 let mut data = [0u8; 4];
216 data.copy_from_slice(&payload[0..4]);
217 Self::Local(Ipv4Addr::from(data))
218 } else {
219 return Err(DecodeError::from(format!(
220 "Invalid IFLA_VXLAN_LOCAL, got unexpected length of \
221 IPv4 address payload {payload:?}"
222 )));
223 }
224 }
225 IFLA_VXLAN_GROUP6 => {
226 if payload.len() == 16 {
227 let mut data = [0u8; 16];
228 data.copy_from_slice(&payload[0..16]);
229 Self::Group6(Ipv6Addr::from(data))
230 } else {
231 return Err(DecodeError::from(format!(
232 "Invalid IFLA_VXLAN_GROUP6, got unexpected length of \
233 IPv6 address payload {payload:?}"
234 )));
235 }
236 }
237 IFLA_VXLAN_LOCAL6 => {
238 if payload.len() == 16 {
239 let mut data = [0u8; 16];
240 data.copy_from_slice(&payload[0..16]);
241 Self::Local6(Ipv6Addr::from(data))
242 } else {
243 return Err(DecodeError::from(format!(
244 "Invalid IFLA_VXLAN_LOCAL6, got unexpected length of \
245 IPv6 address payload {payload:?}"
246 )));
247 }
248 }
249 IFLA_VXLAN_LINK => Self::Link(
250 parse_u32(payload).context("invalid IFLA_VXLAN_LINK value")?,
251 ),
252 IFLA_VXLAN_TOS => Self::Tos(
253 parse_u8(payload).context("invalid IFLA_VXLAN_TOS value")?,
254 ),
255 IFLA_VXLAN_TTL => Self::Ttl(
256 parse_u8(payload).context("invalid IFLA_VXLAN_TTL value")?,
257 ),
258 IFLA_VXLAN_LABEL => Self::Label(
259 parse_u32(payload).context("invalid IFLA_VXLAN_LABEL value")?,
260 ),
261 IFLA_VXLAN_LEARNING => Self::Learning(
262 parse_u8(payload)
263 .context("invalid IFLA_VXLAN_LEARNING value")?
264 > 0,
265 ),
266 IFLA_VXLAN_AGEING => Self::Ageing(
267 parse_u32(payload)
268 .context("invalid IFLA_VXLAN_AGEING value")?,
269 ),
270 IFLA_VXLAN_LIMIT => Self::Limit(
271 parse_u32(payload).context("invalid IFLA_VXLAN_LIMIT value")?,
272 ),
273 IFLA_VXLAN_PROXY => Self::Proxy(
274 parse_u8(payload).context("invalid IFLA_VXLAN_PROXY value")?
275 > 0,
276 ),
277 IFLA_VXLAN_RSC => Self::Rsc(
278 parse_u8(payload).context("invalid IFLA_VXLAN_RSC value")? > 0,
279 ),
280 IFLA_VXLAN_L2MISS => Self::L2Miss(
281 parse_u8(payload).context("invalid IFLA_VXLAN_L2MISS value")?
282 > 0,
283 ),
284 IFLA_VXLAN_L3MISS => Self::L3Miss(
285 parse_u8(payload).context("invalid IFLA_VXLAN_L3MISS value")?
286 > 0,
287 ),
288 IFLA_VXLAN_COLLECT_METADATA => Self::CollectMetadata(
289 parse_u8(payload)
290 .context("invalid IFLA_VXLAN_COLLECT_METADATA value")?
291 > 0,
292 ),
293 IFLA_VXLAN_PORT_RANGE => {
294 let err = "invalid IFLA_VXLAN_PORT value";
295 if payload.len() != 4 {
296 return Err(err.into());
297 }
298 let low = parse_u16_be(&payload[0..2]).context(err)?;
299 let high = parse_u16_be(&payload[2..]).context(err)?;
300 Self::PortRange((low, high))
301 }
302 IFLA_VXLAN_PORT => Self::Port(
303 parse_u16_be(payload)
304 .context("invalid IFLA_VXLAN_PORT value")?,
305 ),
306 IFLA_VXLAN_UDP_CSUM => Self::UDPCsum(
307 parse_u8(payload)
308 .context("invalid IFLA_VXLAN_UDP_CSUM value")?
309 > 0,
310 ),
311 IFLA_VXLAN_UDP_ZERO_CSUM6_TX => Self::UDPZeroCsumTX(
312 parse_u8(payload)
313 .context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_TX value")?
314 > 0,
315 ),
316 IFLA_VXLAN_UDP_ZERO_CSUM6_RX => Self::UDPZeroCsumRX(
317 parse_u8(payload)
318 .context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_RX value")?
319 > 0,
320 ),
321 IFLA_VXLAN_REMCSUM_TX => Self::RemCsumTX(
322 parse_u8(payload)
323 .context("invalid IFLA_VXLAN_REMCSUM_TX value")?
324 > 0,
325 ),
326 IFLA_VXLAN_REMCSUM_RX => Self::RemCsumRX(
327 parse_u8(payload)
328 .context("invalid IFLA_VXLAN_REMCSUM_RX value")?
329 > 0,
330 ),
331 IFLA_VXLAN_DF => Self::Df(
332 parse_u8(payload).context("invalid IFLA_VXLAN_DF value")?,
333 ),
334 IFLA_VXLAN_GBP => Self::Gbp(true),
335 IFLA_VXLAN_GPE => Self::Gpe(true),
336 IFLA_VXLAN_REMCSUM_NOPARTIAL => Self::RemCsumNoPartial(true),
337 IFLA_VXLAN_TTL_INHERIT => Self::TtlInherit(
338 parse_u8(payload)
339 .context("invalid IFLA_VXLAN_TTL_INHERIT value")?
340 > 0,
341 ),
342 IFLA_VXLAN_VNIFILTER => Self::Vnifilter(
343 parse_u8(payload)
344 .context("invalid IFLA_VXLAN_VNIFILTER value")?
345 > 0,
346 ),
347 IFLA_VXLAN_LOCALBYPASS => Self::Localbypass(
348 parse_u8(payload)
349 .context("invalid IFLA_VXLAN_LOCALBYPASS value")?
350 > 0,
351 ),
352 unknown_kind => {
353 Self::Other(DefaultNla::parse(buf).context(format!(
354 "Failed to parse IFLA_INFO_DATA(vxlan) NLA type: \
355 {unknown_kind} as DefaultNla"
356 ))?)
357 }
358 })
359 }
360}