1use crate::{
4 constants::*,
5 nlas::{DefaultNla, Nla, NlaBuffer, NlasIterator},
6 parsers::{parse_mac, parse_string, parse_u16, parse_u16_be, parse_u32, parse_u64, parse_u8},
7 traits::{Emitable, Parseable},
8 DecodeError,
9 LinkMessage,
10 LinkMessageBuffer,
11};
12use anyhow::Context;
13use byteorder::{BigEndian, ByteOrder, NativeEndian};
14
15const DUMMY: &str = "dummy";
16const IFB: &str = "ifb";
17const BRIDGE: &str = "bridge";
18const TUN: &str = "tun";
19const NLMON: &str = "nlmon";
20const VLAN: &str = "vlan";
21const VETH: &str = "veth";
22const VXLAN: &str = "vxlan";
23const BOND: &str = "bond";
24const IPVLAN: &str = "ipvlan";
25const MACVLAN: &str = "macvlan";
26const MACVTAP: &str = "macvtap";
27const GRETAP: &str = "gretap";
28const IP6GRETAP: &str = "ip6gretap";
29const IPIP: &str = "ipip";
30const SIT: &str = "sit";
31const GRE: &str = "gre";
32const IP6GRE: &str = "ip6gre";
33const VTI: &str = "vti";
34const VRF: &str = "vrf";
35const GTP: &str = "gtp";
36const IPOIB: &str = "ipoib";
37const WIREGUARD: &str = "wireguard";
38
39#[derive(Debug, PartialEq, Eq, Clone)]
40pub enum Info {
41 Unspec(Vec<u8>),
42 Xstats(Vec<u8>),
43 Kind(InfoKind),
44 Data(InfoData),
45 SlaveKind(Vec<u8>),
46 SlaveData(Vec<u8>),
47}
48
49impl Nla for Info {
50 #[rustfmt::skip]
51 fn value_len(&self) -> usize {
52 use self::Info::*;
53 match self {
54 Unspec(ref bytes)
55 | Xstats(ref bytes)
56 | SlaveKind(ref bytes)
57 | SlaveData(ref bytes)
58 => bytes.len(),
59 Kind(ref nla) => nla.value_len(),
60 Data(ref nla) => nla.value_len(),
61 }
62 }
63
64 #[rustfmt::skip]
65 fn emit_value(&self, buffer: &mut [u8]) {
66 use self::Info::*;
67 match self {
68 Unspec(ref bytes)
69 | Xstats(ref bytes)
70 | SlaveKind(ref bytes)
71 | SlaveData(ref bytes)
72 => buffer.copy_from_slice(bytes),
73 Kind(ref nla) => nla.emit_value(buffer),
74 Data(ref nla) => nla.emit_value(buffer),
75 }
76 }
77
78 fn kind(&self) -> u16 {
79 use self::Info::*;
80 match self {
81 Unspec(_) => IFLA_INFO_UNSPEC,
82 Xstats(_) => IFLA_INFO_XSTATS,
83 SlaveKind(_) => IFLA_INFO_SLAVE_KIND,
84 SlaveData(_) => IFLA_INFO_DATA,
85 Kind(_) => IFLA_INFO_KIND,
86 Data(_) => IFLA_INFO_DATA,
87 }
88 }
89}
90
91pub(crate) struct VecInfo(pub(crate) Vec<Info>);
92
93impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VecInfo {
104 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
105 let mut res = Vec::new();
106 let nlas = NlasIterator::new(buf.into_inner());
107 let mut link_info_kind: Option<InfoKind> = None;
108 for nla in nlas {
109 let nla = nla?;
110 match nla.kind() {
111 IFLA_INFO_UNSPEC => res.push(Info::Unspec(nla.value().to_vec())),
112 IFLA_INFO_XSTATS => res.push(Info::Xstats(nla.value().to_vec())),
113 IFLA_INFO_SLAVE_KIND => res.push(Info::SlaveKind(nla.value().to_vec())),
114 IFLA_INFO_SLAVE_DATA => res.push(Info::SlaveData(nla.value().to_vec())),
115 IFLA_INFO_KIND => {
116 let parsed = InfoKind::parse(&nla)?;
117 res.push(Info::Kind(parsed.clone()));
118 link_info_kind = Some(parsed);
119 }
120 IFLA_INFO_DATA => {
121 if let Some(link_info_kind) = link_info_kind {
122 let payload = nla.value();
123 let info_data = match link_info_kind {
124 InfoKind::Dummy => InfoData::Dummy(payload.to_vec()),
125 InfoKind::Ifb => InfoData::Ifb(payload.to_vec()),
126 InfoKind::Bridge => {
127 let mut v = Vec::new();
128 let err =
129 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'bridge')";
130 for nla in NlasIterator::new(payload) {
131 let nla = &nla.context(err)?;
132 let parsed = InfoBridge::parse(nla).context(err)?;
133 v.push(parsed);
134 }
135 InfoData::Bridge(v)
136 }
137 InfoKind::Vlan => {
138 let mut v = Vec::new();
139 let err =
140 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vlan')";
141 for nla in NlasIterator::new(payload) {
142 let nla = &nla.context(err)?;
143 let parsed = InfoVlan::parse(nla).context(err)?;
144 v.push(parsed);
145 }
146 InfoData::Vlan(v)
147 }
148 InfoKind::Tun => InfoData::Tun(payload.to_vec()),
149 InfoKind::Nlmon => InfoData::Nlmon(payload.to_vec()),
150 InfoKind::Veth => {
151 let err =
152 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'veth')";
153 let nla_buf = NlaBuffer::new_checked(&payload).context(err)?;
154 let parsed = VethInfo::parse(&nla_buf).context(err)?;
155 InfoData::Veth(parsed)
156 }
157 InfoKind::Vxlan => {
158 let mut v = Vec::new();
159 let err =
160 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vxlan')";
161 for nla in NlasIterator::new(payload) {
162 let nla = &nla.context(err)?;
163 let parsed = InfoVxlan::parse(nla).context(err)?;
164 v.push(parsed);
165 }
166 InfoData::Vxlan(v)
167 }
168 InfoKind::Bond => InfoData::Bond(payload.to_vec()),
169 InfoKind::IpVlan => {
170 let mut v = Vec::new();
171 let err =
172 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'ipvlan')";
173 for nla in NlasIterator::new(payload) {
174 let nla = &nla.context(err)?;
175 let parsed = InfoIpVlan::parse(nla).context(err)?;
176 v.push(parsed);
177 }
178 InfoData::IpVlan(v)
179 }
180 InfoKind::MacVlan => {
181 let mut v = Vec::new();
182 let err =
183 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'macvlan')";
184 for nla in NlasIterator::new(payload) {
185 let nla = &nla.context(err)?;
186 let parsed = InfoMacVlan::parse(nla).context(err)?;
187 v.push(parsed);
188 }
189 InfoData::MacVlan(v)
190 }
191 InfoKind::MacVtap => {
192 let mut v = Vec::new();
193 let err =
194 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'macvtap')";
195 for nla in NlasIterator::new(payload) {
196 let nla = &nla.context(err)?;
197 let parsed = InfoMacVtap::parse(nla).context(err)?;
198 v.push(parsed);
199 }
200 InfoData::MacVtap(v)
201 }
202 InfoKind::GreTap => InfoData::GreTap(payload.to_vec()),
203 InfoKind::GreTap6 => InfoData::GreTap6(payload.to_vec()),
204 InfoKind::IpTun => InfoData::IpTun(payload.to_vec()),
205 InfoKind::SitTun => InfoData::SitTun(payload.to_vec()),
206 InfoKind::GreTun => InfoData::GreTun(payload.to_vec()),
207 InfoKind::GreTun6 => InfoData::GreTun6(payload.to_vec()),
208 InfoKind::Vti => InfoData::Vti(payload.to_vec()),
209 InfoKind::Vrf => {
210 let mut v = Vec::new();
211 let err =
212 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vrf')";
213 for nla in NlasIterator::new(payload) {
214 let nla = &nla.context(err)?;
215 let parsed = InfoVrf::parse(nla).context(err)?;
216 v.push(parsed);
217 }
218 InfoData::Vrf(v)
219 }
220 InfoKind::Gtp => InfoData::Gtp(payload.to_vec()),
221 InfoKind::Ipoib => {
222 let mut v = Vec::new();
223 let err =
224 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'ipoib')";
225 for nla in NlasIterator::new(payload) {
226 let nla = &nla.context(err)?;
227 let parsed = InfoIpoib::parse(nla).context(err)?;
228 v.push(parsed);
229 }
230 InfoData::Ipoib(v)
231 }
232 InfoKind::Wireguard => InfoData::Wireguard(payload.to_vec()),
233 InfoKind::Other(_) => InfoData::Other(payload.to_vec()),
234 };
235 res.push(Info::Data(info_data));
236 } else {
237 return Err("IFLA_INFO_DATA is not preceded by an IFLA_INFO_KIND".into());
238 }
239 link_info_kind = None;
240 }
241 _ => return Err(format!("unknown NLA type {}", nla.kind()).into()),
242 }
243 }
244 Ok(VecInfo(res))
245 }
246}
247
248#[derive(Debug, PartialEq, Eq, Clone)]
249pub enum InfoData {
250 Bridge(Vec<InfoBridge>),
251 Tun(Vec<u8>),
252 Nlmon(Vec<u8>),
253 Vlan(Vec<InfoVlan>),
254 Dummy(Vec<u8>),
255 Ifb(Vec<u8>),
256 Veth(VethInfo),
257 Vxlan(Vec<InfoVxlan>),
258 Bond(Vec<u8>),
259 IpVlan(Vec<InfoIpVlan>),
260 MacVlan(Vec<InfoMacVlan>),
261 MacVtap(Vec<InfoMacVtap>),
262 GreTap(Vec<u8>),
263 GreTap6(Vec<u8>),
264 IpTun(Vec<u8>),
265 SitTun(Vec<u8>),
266 GreTun(Vec<u8>),
267 GreTun6(Vec<u8>),
268 Vti(Vec<u8>),
269 Vrf(Vec<InfoVrf>),
270 Gtp(Vec<u8>),
271 Ipoib(Vec<InfoIpoib>),
272 Wireguard(Vec<u8>),
273 Other(Vec<u8>),
274}
275
276impl Nla for InfoData {
277 #[rustfmt::skip]
278 fn value_len(&self) -> usize {
279 use self::InfoData::*;
280 match self {
281 Bridge(ref nlas) => nlas.as_slice().buffer_len(),
282 Vlan(ref nlas) => nlas.as_slice().buffer_len(),
283 Veth(ref msg) => msg.buffer_len(),
284 IpVlan(ref nlas) => nlas.as_slice().buffer_len(),
285 Ipoib(ref nlas) => nlas.as_slice().buffer_len(),
286 MacVlan(ref nlas) => nlas.as_slice().buffer_len(),
287 MacVtap(ref nlas) => nlas.as_slice().buffer_len(),
288 Vrf(ref nlas) => nlas.as_slice().buffer_len(),
289 Vxlan(ref nlas) => nlas.as_slice().buffer_len(),
290 Dummy(ref bytes)
291 | Tun(ref bytes)
292 | Nlmon(ref bytes)
293 | Ifb(ref bytes)
294 | Bond(ref bytes)
295 | GreTap(ref bytes)
296 | GreTap6(ref bytes)
297 | IpTun(ref bytes)
298 | SitTun(ref bytes)
299 | GreTun(ref bytes)
300 | GreTun6(ref bytes)
301 | Vti(ref bytes)
302 | Gtp(ref bytes)
303 | Wireguard(ref bytes)
304 | Other(ref bytes)
305 => bytes.len(),
306 }
307 }
308
309 #[rustfmt::skip]
310 fn emit_value(&self, buffer: &mut [u8]) {
311 use self::InfoData::*;
312 match self {
313 Bridge(ref nlas) => nlas.as_slice().emit(buffer),
314 Vlan(ref nlas) => nlas.as_slice().emit(buffer),
315 Veth(ref msg) => msg.emit(buffer),
316 IpVlan(ref nlas) => nlas.as_slice().emit(buffer),
317 Ipoib(ref nlas) => nlas.as_slice().emit(buffer),
318 MacVlan(ref nlas) => nlas.as_slice().emit(buffer),
319 MacVtap(ref nlas) => nlas.as_slice().emit(buffer),
320 Vrf(ref nlas) => nlas.as_slice().emit(buffer),
321 Vxlan(ref nlas) => nlas.as_slice().emit(buffer),
322 Dummy(ref bytes)
323 | Tun(ref bytes)
324 | Nlmon(ref bytes)
325 | Ifb(ref bytes)
326 | Bond(ref bytes)
327 | GreTap(ref bytes)
328 | GreTap6(ref bytes)
329 | IpTun(ref bytes)
330 | SitTun(ref bytes)
331 | GreTun(ref bytes)
332 | GreTun6(ref bytes)
333 | Vti(ref bytes)
334 | Gtp(ref bytes)
335 | Wireguard(ref bytes)
336 | Other(ref bytes)
337 => buffer.copy_from_slice(bytes),
338 }
339 }
340
341 fn kind(&self) -> u16 {
342 IFLA_INFO_DATA
343 }
344}
345
346#[derive(Debug, PartialEq, Eq, Clone)]
347pub enum InfoKind {
348 Dummy,
349 Ifb,
350 Bridge,
351 Tun,
352 Nlmon,
353 Vlan,
354 Veth,
355 Vxlan,
356 Bond,
357 IpVlan,
358 MacVlan,
359 MacVtap,
360 GreTap,
361 GreTap6,
362 IpTun,
363 SitTun,
364 GreTun,
365 GreTun6,
366 Vti,
367 Vrf,
368 Gtp,
369 Ipoib,
370 Wireguard,
371 Other(String),
372}
373
374impl Nla for InfoKind {
375 fn value_len(&self) -> usize {
376 use self::InfoKind::*;
377 let len = match *self {
378 Dummy => DUMMY.len(),
379 Ifb => IFB.len(),
380 Bridge => BRIDGE.len(),
381 Tun => TUN.len(),
382 Nlmon => NLMON.len(),
383 Vlan => VLAN.len(),
384 Veth => VETH.len(),
385 Vxlan => VXLAN.len(),
386 Bond => BOND.len(),
387 IpVlan => IPVLAN.len(),
388 MacVlan => MACVLAN.len(),
389 MacVtap => MACVTAP.len(),
390 GreTap => GRETAP.len(),
391 GreTap6 => IP6GRETAP.len(),
392 IpTun => IPIP.len(),
393 SitTun => SIT.len(),
394 GreTun => GRE.len(),
395 GreTun6 => IP6GRE.len(),
396 Vti => VTI.len(),
397 Vrf => VRF.len(),
398 Gtp => GTP.len(),
399 Ipoib => IPOIB.len(),
400 Wireguard => WIREGUARD.len(),
401 Other(ref s) => s.len(),
402 };
403 len + 1
404 }
405
406 fn emit_value(&self, buffer: &mut [u8]) {
407 use self::InfoKind::*;
408 let s = match *self {
409 Dummy => DUMMY,
410 Ifb => IFB,
411 Bridge => BRIDGE,
412 Tun => TUN,
413 Nlmon => NLMON,
414 Vlan => VLAN,
415 Veth => VETH,
416 Vxlan => VXLAN,
417 Bond => BOND,
418 IpVlan => IPVLAN,
419 MacVlan => MACVLAN,
420 MacVtap => MACVTAP,
421 GreTap => GRETAP,
422 GreTap6 => IP6GRETAP,
423 IpTun => IPIP,
424 SitTun => SIT,
425 GreTun => GRE,
426 GreTun6 => IP6GRE,
427 Vti => VTI,
428 Vrf => VRF,
429 Gtp => GTP,
430 Ipoib => IPOIB,
431 Wireguard => WIREGUARD,
432 Other(ref s) => s.as_str(),
433 };
434 buffer[..s.len()].copy_from_slice(s.as_bytes());
435 buffer[s.len()] = 0;
436 }
437
438 fn kind(&self) -> u16 {
439 IFLA_INFO_KIND
440 }
441}
442
443impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoKind {
444 fn parse(buf: &NlaBuffer<&'a T>) -> Result<InfoKind, DecodeError> {
445 use self::InfoKind::*;
446 if buf.kind() != IFLA_INFO_KIND {
447 return Err(
448 format!("failed to parse IFLA_INFO_KIND: NLA type is {}", buf.kind()).into(),
449 );
450 }
451 let s = parse_string(buf.value()).context("invalid IFLA_INFO_KIND value")?;
452 Ok(match s.as_str() {
453 DUMMY => Dummy,
454 IFB => Ifb,
455 BRIDGE => Bridge,
456 TUN => Tun,
457 NLMON => Nlmon,
458 VLAN => Vlan,
459 VETH => Veth,
460 VXLAN => Vxlan,
461 BOND => Bond,
462 IPVLAN => IpVlan,
463 MACVLAN => MacVlan,
464 MACVTAP => MacVtap,
465 GRETAP => GreTap,
466 IP6GRETAP => GreTap6,
467 IPIP => IpTun,
468 SIT => SitTun,
469 GRE => GreTun,
470 IP6GRE => GreTun6,
471 VTI => Vti,
472 VRF => Vrf,
473 GTP => Gtp,
474 IPOIB => Ipoib,
475 WIREGUARD => Wireguard,
476 _ => Other(s),
477 })
478 }
479}
480
481#[derive(Debug, PartialEq, Eq, Clone)]
483pub enum InfoVxlan {
484 Unspec(Vec<u8>),
485 Id(u32),
486 Group(Vec<u8>),
487 Group6(Vec<u8>),
488 Link(u32),
489 Local(Vec<u8>),
490 Local6(Vec<u8>),
491 Tos(u8),
492 Ttl(u8),
493 Label(u32),
494 Learning(u8),
495 Ageing(u32),
496 Limit(u32),
497 PortRange((u16, u16)),
498 Proxy(u8),
499 Rsc(u8),
500 L2Miss(u8),
501 L3Miss(u8),
502 CollectMetadata(u8),
503 Port(u16),
504 UDPCsum(u8),
505 UDPZeroCsumTX(u8),
506 UDPZeroCsumRX(u8),
507 RemCsumTX(u8),
508 RemCsumRX(u8),
509 Gbp(u8),
510 Gpe(u8),
511 RemCsumNoPartial(u8),
512 TtlInherit(u8),
513 Df(u8),
514}
515
516impl Nla for InfoVxlan {
517 #[rustfmt::skip]
518 fn value_len(&self) -> usize {
519 use self::InfoVxlan::*;
520 match *self {
521 Tos(_)
522 | Ttl(_)
523 | Learning(_)
524 | Proxy(_)
525 | Rsc(_)
526 | L2Miss(_)
527 | L3Miss(_)
528 | CollectMetadata(_)
529 | UDPCsum(_)
530 | UDPZeroCsumTX(_)
531 | UDPZeroCsumRX(_)
532 | RemCsumTX(_)
533 | RemCsumRX(_)
534 | Gbp(_)
535 | Gpe(_)
536 | RemCsumNoPartial(_)
537 | TtlInherit(_)
538 | Df(_)
539 => 1,
540 Port(_) => 2,
541 Id(_)
542 | Label(_)
543 | Link(_)
544 | Ageing(_)
545 | Limit(_)
546 | PortRange(_)
547 => 4,
548 Local(ref bytes)
549 | Local6(ref bytes)
550 | Group(ref bytes)
551 | Group6(ref bytes)
552 | Unspec(ref bytes)
553 => bytes.len(),
554 }
555 }
556
557 #[rustfmt::skip]
558 fn emit_value(&self, buffer: &mut [u8]) {
559 use self::InfoVxlan::*;
560 match self {
561 Unspec(ref bytes) => buffer.copy_from_slice(bytes),
562 Id(ref value)
563 | Label(ref value)
564 | Link(ref value)
565 | Ageing(ref value)
566 | Limit(ref value)
567 => NativeEndian::write_u32(buffer, *value),
568 Tos(ref value)
569 | Ttl(ref value)
570 | Learning (ref value)
571 | Proxy(ref value)
572 | Rsc(ref value)
573 | L2Miss(ref value)
574 | L3Miss(ref value)
575 | CollectMetadata(ref value)
576 | UDPCsum(ref value)
577 | UDPZeroCsumTX(ref value)
578 | UDPZeroCsumRX(ref value)
579 | RemCsumTX(ref value)
580 | RemCsumRX(ref value)
581 | Gbp(ref value)
582 | Gpe(ref value)
583 | RemCsumNoPartial(ref value)
584 | TtlInherit(ref value)
585 | Df(ref value)
586 => buffer[0] = *value,
587 Local(ref value)
588 | Group(ref value)
589 | Group6(ref value)
590 | Local6(ref value)
591 => buffer.copy_from_slice(value.as_slice()),
592 Port(ref value) => NativeEndian::write_u16(buffer, *value),
593 PortRange(ref range) => {
594 NativeEndian::write_u16(buffer, range.0);
595 NativeEndian::write_u16(buffer, range.1)
596 }
597 }
598 }
599
600 fn kind(&self) -> u16 {
601 use self::InfoVxlan::*;
602
603 match self {
604 Id(_) => IFLA_VXLAN_ID,
605 Group(_) => IFLA_VXLAN_GROUP,
606 Group6(_) => IFLA_VXLAN_GROUP6,
607 Link(_) => IFLA_VXLAN_LINK,
608 Local(_) => IFLA_VXLAN_LOCAL,
609 Local6(_) => IFLA_VXLAN_LOCAL6,
610 Tos(_) => IFLA_VXLAN_TOS,
611 Ttl(_) => IFLA_VXLAN_TTL,
612 Label(_) => IFLA_VXLAN_LABEL,
613 Learning(_) => IFLA_VXLAN_LEARNING,
614 Ageing(_) => IFLA_VXLAN_AGEING,
615 Limit(_) => IFLA_VXLAN_LIMIT,
616 PortRange(_) => IFLA_VXLAN_PORT_RANGE,
617 Proxy(_) => IFLA_VXLAN_PROXY,
618 Rsc(_) => IFLA_VXLAN_RSC,
619 L2Miss(_) => IFLA_VXLAN_L2MISS,
620 L3Miss(_) => IFLA_VXLAN_L3MISS,
621 CollectMetadata(_) => IFLA_VXLAN_COLLECT_METADATA,
622 Port(_) => IFLA_VXLAN_PORT,
623 UDPCsum(_) => IFLA_VXLAN_UDP_CSUM,
624 UDPZeroCsumTX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
625 UDPZeroCsumRX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
626 RemCsumTX(_) => IFLA_VXLAN_REMCSUM_TX,
627 RemCsumRX(_) => IFLA_VXLAN_REMCSUM_RX,
628 Gbp(_) => IFLA_VXLAN_GBP,
629 Gpe(_) => IFLA_VXLAN_GPE,
630 RemCsumNoPartial(_) => IFLA_VXLAN_REMCSUM_NOPARTIAL,
631 TtlInherit(_) => IFLA_VXLAN_TTL_INHERIT,
632 Df(_) => IFLA_VXLAN_DF,
633 Unspec(_) => IFLA_VXLAN_UNSPEC,
634 }
635 }
636}
637
638impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVxlan {
639 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
640 use self::InfoVxlan::*;
641 let payload = buf.value();
642 Ok(match buf.kind() {
643 IFLA_VLAN_UNSPEC => Unspec(payload.to_vec()),
644 IFLA_VXLAN_ID => Id(parse_u32(payload).context("invalid IFLA_VXLAN_ID value")?),
645 IFLA_VXLAN_GROUP => Group(payload.to_vec()),
646 IFLA_VXLAN_GROUP6 => Group6(payload.to_vec()),
647 IFLA_VXLAN_LINK => Link(parse_u32(payload).context("invalid IFLA_VXLAN_LINK value")?),
648 IFLA_VXLAN_LOCAL => Local(payload.to_vec()),
649 IFLA_VXLAN_LOCAL6 => Local6(payload.to_vec()),
650 IFLA_VXLAN_TOS => Tos(parse_u8(payload).context("invalid IFLA_VXLAN_TOS value")?),
651 IFLA_VXLAN_TTL => Ttl(parse_u8(payload).context("invalid IFLA_VXLAN_TTL value")?),
652 IFLA_VXLAN_LABEL => {
653 Label(parse_u32(payload).context("invalid IFLA_VXLAN_LABEL value")?)
654 }
655 IFLA_VXLAN_LEARNING => {
656 Learning(parse_u8(payload).context("invalid IFLA_VXLAN_LEARNING value")?)
657 }
658 IFLA_VXLAN_AGEING => {
659 Ageing(parse_u32(payload).context("invalid IFLA_VXLAN_AGEING value")?)
660 }
661 IFLA_VXLAN_LIMIT => {
662 Limit(parse_u32(payload).context("invalid IFLA_VXLAN_LIMIT value")?)
663 }
664 IFLA_VXLAN_PROXY => Proxy(parse_u8(payload).context("invalid IFLA_VXLAN_PROXY value")?),
665 IFLA_VXLAN_RSC => Rsc(parse_u8(payload).context("invalid IFLA_VXLAN_RSC value")?),
666 IFLA_VXLAN_L2MISS => {
667 L2Miss(parse_u8(payload).context("invalid IFLA_VXLAN_L2MISS value")?)
668 }
669 IFLA_VXLAN_L3MISS => {
670 L3Miss(parse_u8(payload).context("invalid IFLA_VXLAN_L3MISS value")?)
671 }
672 IFLA_VXLAN_COLLECT_METADATA => CollectMetadata(
673 parse_u8(payload).context("invalid IFLA_VXLAN_COLLECT_METADATA value")?,
674 ),
675 IFLA_VXLAN_PORT_RANGE => {
676 let err = "invalid IFLA_VXLAN_PORT value";
677 if payload.len() != 4 {
678 return Err(err.into());
679 }
680 let low = parse_u16(&payload[0..2]).context(err)?;
681 let high = parse_u16(&payload[2..]).context(err)?;
682 PortRange((low, high))
683 }
684 IFLA_VXLAN_PORT => {
685 Port(parse_u16_be(payload).context("invalid IFLA_VXLAN_PORT value")?)
686 }
687 IFLA_VXLAN_UDP_CSUM => {
688 UDPCsum(parse_u8(payload).context("invalid IFLA_VXLAN_UDP_CSUM value")?)
689 }
690 IFLA_VXLAN_UDP_ZERO_CSUM6_TX => UDPZeroCsumTX(
691 parse_u8(payload).context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_TX value")?,
692 ),
693 IFLA_VXLAN_UDP_ZERO_CSUM6_RX => UDPZeroCsumRX(
694 parse_u8(payload).context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_RX value")?,
695 ),
696 IFLA_VXLAN_REMCSUM_TX => {
697 RemCsumTX(parse_u8(payload).context("invalid IFLA_VXLAN_REMCSUM_TX value")?)
698 }
699 IFLA_VXLAN_REMCSUM_RX => {
700 RemCsumRX(parse_u8(payload).context("invalid IFLA_VXLAN_REMCSUM_RX value")?)
701 }
702 IFLA_VXLAN_DF => Df(parse_u8(payload).context("invalid IFLA_VXLAN_DF value")?),
703 IFLA_VXLAN_GBP => Gbp(parse_u8(payload).context("invalid IFLA_VXLAN_GBP value")?),
704 IFLA_VXLAN_GPE => Gpe(parse_u8(payload).context("invalid IFLA_VXLAN_GPE value")?),
705 IFLA_VXLAN_REMCSUM_NOPARTIAL => RemCsumNoPartial(
706 parse_u8(payload).context("invalid IFLA_VXLAN_REMCSUM_NO_PARTIAL")?,
707 ),
708 IFLA_VXLAN_TTL_INHERIT => {
709 TtlInherit(parse_u8(payload).context("invalid IFLA_VXLAN_TTL_INHERIT value")?)
710 }
711 __IFLA_VXLAN_MAX => Unspec(payload.to_vec()),
712 _ => return Err(format!("unknown NLA type {}", buf.kind()).into()),
713 })
714 }
715}
716
717#[derive(Debug, PartialEq, Eq, Clone)]
719pub enum InfoVlan {
720 Unspec(Vec<u8>),
721 Id(u16),
722 Flags((u32, u32)),
723 EgressQos(Vec<u8>),
724 IngressQos(Vec<u8>),
725 Protocol(u16),
726}
727
728impl Nla for InfoVlan {
729 #[rustfmt::skip]
730 fn value_len(&self) -> usize {
731 use self::InfoVlan::*;
732 match self {
733 Id(_) | Protocol(_) => 2,
734 Flags(_) => 8,
735 Unspec(bytes)
736 | EgressQos(bytes)
737 | IngressQos(bytes)
738 => bytes.len(),
739 }
740 }
741
742 #[rustfmt::skip]
743 fn emit_value(&self, buffer: &mut [u8]) {
744 use self::InfoVlan::*;
745 match self {
746 Unspec(ref bytes)
747 | EgressQos(ref bytes)
748 | IngressQos(ref bytes)
749 => buffer.copy_from_slice(bytes),
750
751 Id(ref value)
752 | Protocol(ref value)
753 => NativeEndian::write_u16(buffer, *value),
754
755 Flags(ref flags) => {
756 NativeEndian::write_u32(buffer, flags.0);
757 NativeEndian::write_u32(buffer, flags.1)
758 }
759 }
760 }
761
762 fn kind(&self) -> u16 {
763 use self::InfoVlan::*;
764 match self {
765 Unspec(_) => IFLA_VLAN_UNSPEC,
766 Id(_) => IFLA_VLAN_ID,
767 Flags(_) => IFLA_VLAN_FLAGS,
768 EgressQos(_) => IFLA_VLAN_EGRESS_QOS,
769 IngressQos(_) => IFLA_VLAN_INGRESS_QOS,
770 Protocol(_) => IFLA_VLAN_PROTOCOL,
771 }
772 }
773}
774
775impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVlan {
776 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
777 use self::InfoVlan::*;
778 let payload = buf.value();
779 Ok(match buf.kind() {
780 IFLA_VLAN_UNSPEC => Unspec(payload.to_vec()),
781 IFLA_VLAN_ID => Id(parse_u16(payload).context("invalid IFLA_VLAN_ID value")?),
782 IFLA_VLAN_FLAGS => {
783 let err = "invalid IFLA_VLAN_FLAGS value";
784 if payload.len() != 8 {
785 return Err(err.into());
786 }
787 let flags = parse_u32(&payload[0..4]).context(err)?;
788 let mask = parse_u32(&payload[4..]).context(err)?;
789 Flags((flags, mask))
790 }
791 IFLA_VLAN_EGRESS_QOS => EgressQos(payload.to_vec()),
792 IFLA_VLAN_INGRESS_QOS => IngressQos(payload.to_vec()),
793 IFLA_VLAN_PROTOCOL => {
794 Protocol(parse_u16_be(payload).context("invalid IFLA_VLAN_PROTOCOL value")?)
795 }
796 _ => return Err(format!("unknown NLA type {}", buf.kind()).into()),
797 })
798 }
799}
800
801#[derive(Debug, PartialEq, Eq, Clone)]
802pub enum InfoBridge {
803 Unspec(Vec<u8>),
804 GroupAddr([u8; 6]),
805 FdbFlush(Vec<u8>),
808 Pad(Vec<u8>),
809 HelloTimer(u64),
810 TcnTimer(u64),
811 TopologyChangeTimer(u64),
812 GcTimer(u64),
813 MulticastMembershipInterval(u64),
814 MulticastQuerierInterval(u64),
815 MulticastQueryInterval(u64),
816 MulticastQueryResponseInterval(u64),
817 MulticastLastMemberInterval(u64),
818 MulticastStartupQueryInterval(u64),
819 ForwardDelay(u32),
820 HelloTime(u32),
821 MaxAge(u32),
822 AgeingTime(u32),
823 StpState(u32),
824 MulticastHashElasticity(u32),
825 MulticastHashMax(u32),
826 MulticastLastMemberCount(u32),
827 MulticastStartupQueryCount(u32),
828 RootPathCost(u32),
829 Priority(u16),
830 VlanProtocol(u16),
831 GroupFwdMask(u16),
832 RootId((u16, [u8; 6])),
833 BridgeId((u16, [u8; 6])),
834 RootPort(u16),
835 VlanDefaultPvid(u16),
836 VlanFiltering(u8),
837 TopologyChange(u8),
838 TopologyChangeDetected(u8),
839 MulticastRouter(u8),
840 MulticastSnooping(u8),
841 MulticastQueryUseIfaddr(u8),
842 MulticastQuerier(u8),
843 NfCallIpTables(u8),
844 NfCallIp6Tables(u8),
845 NfCallArpTables(u8),
846 VlanStatsEnabled(u8),
847 MulticastStatsEnabled(u8),
848 MulticastIgmpVersion(u8),
849 MulticastMldVersion(u8),
850 VlanStatsPerHost(u8),
851 MultiBoolOpt(u64),
852 Other(DefaultNla),
853}
854
855impl Nla for InfoBridge {
856 #[rustfmt::skip]
857 fn value_len(&self) -> usize {
858 use self::InfoBridge::*;
859 match self {
860 Unspec(bytes)
861 | FdbFlush(bytes)
862 | Pad(bytes)
863 => bytes.len(),
864 HelloTimer(_)
865 | TcnTimer(_)
866 | TopologyChangeTimer(_)
867 | GcTimer(_)
868 | MulticastMembershipInterval(_)
869 | MulticastQuerierInterval(_)
870 | MulticastQueryInterval(_)
871 | MulticastQueryResponseInterval(_)
872 | MulticastLastMemberInterval(_)
873 | MulticastStartupQueryInterval(_)
874 => 8,
875 ForwardDelay(_)
876 | HelloTime(_)
877 | MaxAge(_)
878 | AgeingTime(_)
879 | StpState(_)
880 | MulticastHashElasticity(_)
881 | MulticastHashMax(_)
882 | MulticastLastMemberCount(_)
883 | MulticastStartupQueryCount(_)
884 | RootPathCost(_)
885 => 4,
886 Priority(_)
887 | VlanProtocol(_)
888 | GroupFwdMask(_)
889 | RootPort(_)
890 | VlanDefaultPvid(_)
891 => 2,
892
893 RootId(_)
894 | BridgeId(_)
895 | MultiBoolOpt(_)
896 => 8,
897
898 GroupAddr(_) => 6,
899
900 VlanFiltering(_)
901 | TopologyChange(_)
902 | TopologyChangeDetected(_)
903 | MulticastRouter(_)
904 | MulticastSnooping(_)
905 | MulticastQueryUseIfaddr(_)
906 | MulticastQuerier(_)
907 | NfCallIpTables(_)
908 | NfCallIp6Tables(_)
909 | NfCallArpTables(_)
910 | VlanStatsEnabled(_)
911 | MulticastStatsEnabled(_)
912 | MulticastIgmpVersion(_)
913 | MulticastMldVersion(_)
914 | VlanStatsPerHost(_)
915 => 1,
916 Other(nla)
917 => nla.value_len(),
918 }
919 }
920
921 #[rustfmt::skip]
922 fn emit_value(&self, buffer: &mut [u8]) {
923 use self::InfoBridge::*;
924 match self {
925 Unspec(ref bytes)
926 | FdbFlush(ref bytes)
927 | Pad(ref bytes)
928 => buffer.copy_from_slice(bytes),
929
930 HelloTimer(ref value)
931 | TcnTimer(ref value)
932 | TopologyChangeTimer(ref value)
933 | GcTimer(ref value)
934 | MulticastMembershipInterval(ref value)
935 | MulticastQuerierInterval(ref value)
936 | MulticastQueryInterval(ref value)
937 | MulticastQueryResponseInterval(ref value)
938 | MulticastLastMemberInterval(ref value)
939 | MulticastStartupQueryInterval(ref value)
940 | MultiBoolOpt(ref value)
941 => NativeEndian::write_u64(buffer, *value),
942
943 ForwardDelay(ref value)
944 | HelloTime(ref value)
945 | MaxAge(ref value)
946 | AgeingTime(ref value)
947 | StpState(ref value)
948 | MulticastHashElasticity(ref value)
949 | MulticastHashMax(ref value)
950 | MulticastLastMemberCount(ref value)
951 | MulticastStartupQueryCount(ref value)
952 | RootPathCost(ref value)
953 => NativeEndian::write_u32(buffer, *value),
954
955 Priority(ref value)
956 | GroupFwdMask(ref value)
957 | RootPort(ref value)
958 | VlanDefaultPvid(ref value)
959 => NativeEndian::write_u16(buffer, *value),
960
961 VlanProtocol(ref value)
962 => BigEndian::write_u16(buffer, *value),
963
964 RootId((ref priority, ref address))
965 | BridgeId((ref priority, ref address))
966 => {
967 NativeEndian::write_u16(buffer, *priority);
968 buffer[2..].copy_from_slice(&address[..]);
969 }
970
971 GroupAddr(ref value) => buffer.copy_from_slice(&value[..]),
972
973 VlanFiltering(ref value)
974 | TopologyChange(ref value)
975 | TopologyChangeDetected(ref value)
976 | MulticastRouter(ref value)
977 | MulticastSnooping(ref value)
978 | MulticastQueryUseIfaddr(ref value)
979 | MulticastQuerier(ref value)
980 | NfCallIpTables(ref value)
981 | NfCallIp6Tables(ref value)
982 | NfCallArpTables(ref value)
983 | VlanStatsEnabled(ref value)
984 | MulticastStatsEnabled(ref value)
985 | MulticastIgmpVersion(ref value)
986 | MulticastMldVersion(ref value)
987 | VlanStatsPerHost(ref value)
988 => buffer[0] = *value,
989
990 Other(nla)
991 => nla.emit_value(buffer),
992 }
993 }
994
995 fn kind(&self) -> u16 {
996 use self::InfoBridge::*;
997 match self {
998 Unspec(_) => IFLA_BR_UNSPEC,
999 GroupAddr(_) => IFLA_BR_GROUP_ADDR,
1000 FdbFlush(_) => IFLA_BR_FDB_FLUSH,
1001 Pad(_) => IFLA_BR_PAD,
1002 HelloTimer(_) => IFLA_BR_HELLO_TIMER,
1003 TcnTimer(_) => IFLA_BR_TCN_TIMER,
1004 TopologyChangeTimer(_) => IFLA_BR_TOPOLOGY_CHANGE_TIMER,
1005 GcTimer(_) => IFLA_BR_GC_TIMER,
1006 MulticastMembershipInterval(_) => IFLA_BR_MCAST_MEMBERSHIP_INTVL,
1007 MulticastQuerierInterval(_) => IFLA_BR_MCAST_QUERIER_INTVL,
1008 MulticastQueryInterval(_) => IFLA_BR_MCAST_QUERY_INTVL,
1009 MulticastQueryResponseInterval(_) => IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
1010 ForwardDelay(_) => IFLA_BR_FORWARD_DELAY,
1011 HelloTime(_) => IFLA_BR_HELLO_TIME,
1012 MaxAge(_) => IFLA_BR_MAX_AGE,
1013 AgeingTime(_) => IFLA_BR_AGEING_TIME,
1014 StpState(_) => IFLA_BR_STP_STATE,
1015 MulticastHashElasticity(_) => IFLA_BR_MCAST_HASH_ELASTICITY,
1016 MulticastHashMax(_) => IFLA_BR_MCAST_HASH_MAX,
1017 MulticastLastMemberCount(_) => IFLA_BR_MCAST_LAST_MEMBER_CNT,
1018 MulticastStartupQueryCount(_) => IFLA_BR_MCAST_STARTUP_QUERY_CNT,
1019 MulticastLastMemberInterval(_) => IFLA_BR_MCAST_LAST_MEMBER_INTVL,
1020 MulticastStartupQueryInterval(_) => IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
1021 RootPathCost(_) => IFLA_BR_ROOT_PATH_COST,
1022 Priority(_) => IFLA_BR_PRIORITY,
1023 VlanProtocol(_) => IFLA_BR_VLAN_PROTOCOL,
1024 GroupFwdMask(_) => IFLA_BR_GROUP_FWD_MASK,
1025 RootId(_) => IFLA_BR_ROOT_ID,
1026 BridgeId(_) => IFLA_BR_BRIDGE_ID,
1027 RootPort(_) => IFLA_BR_ROOT_PORT,
1028 VlanDefaultPvid(_) => IFLA_BR_VLAN_DEFAULT_PVID,
1029 VlanFiltering(_) => IFLA_BR_VLAN_FILTERING,
1030 TopologyChange(_) => IFLA_BR_TOPOLOGY_CHANGE,
1031 TopologyChangeDetected(_) => IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
1032 MulticastRouter(_) => IFLA_BR_MCAST_ROUTER,
1033 MulticastSnooping(_) => IFLA_BR_MCAST_SNOOPING,
1034 MulticastQueryUseIfaddr(_) => IFLA_BR_MCAST_QUERY_USE_IFADDR,
1035 MulticastQuerier(_) => IFLA_BR_MCAST_QUERIER,
1036 NfCallIpTables(_) => IFLA_BR_NF_CALL_IPTABLES,
1037 NfCallIp6Tables(_) => IFLA_BR_NF_CALL_IP6TABLES,
1038 NfCallArpTables(_) => IFLA_BR_NF_CALL_ARPTABLES,
1039 VlanStatsEnabled(_) => IFLA_BR_VLAN_STATS_ENABLED,
1040 MulticastStatsEnabled(_) => IFLA_BR_MCAST_STATS_ENABLED,
1041 MulticastIgmpVersion(_) => IFLA_BR_MCAST_IGMP_VERSION,
1042 MulticastMldVersion(_) => IFLA_BR_MCAST_MLD_VERSION,
1043 VlanStatsPerHost(_) => IFLA_BR_VLAN_STATS_PER_PORT,
1044 MultiBoolOpt(_) => IFLA_BR_MULTI_BOOLOPT,
1045 Other(nla) => nla.kind(),
1046 }
1047 }
1048}
1049
1050impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoBridge {
1051 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1052 use self::InfoBridge::*;
1053 let payload = buf.value();
1054 Ok(match buf.kind() {
1055 IFLA_BR_UNSPEC => Unspec(payload.to_vec()),
1056 IFLA_BR_FDB_FLUSH => FdbFlush(payload.to_vec()),
1057 IFLA_BR_PAD => Pad(payload.to_vec()),
1058 IFLA_BR_HELLO_TIMER => {
1059 HelloTimer(parse_u64(payload).context("invalid IFLA_BR_HELLO_TIMER value")?)
1060 }
1061 IFLA_BR_TCN_TIMER => {
1062 TcnTimer(parse_u64(payload).context("invalid IFLA_BR_TCN_TIMER value")?)
1063 }
1064 IFLA_BR_TOPOLOGY_CHANGE_TIMER => TopologyChangeTimer(
1065 parse_u64(payload).context("invalid IFLA_BR_TOPOLOGY_CHANGE_TIMER value")?,
1066 ),
1067 IFLA_BR_GC_TIMER => {
1068 GcTimer(parse_u64(payload).context("invalid IFLA_BR_GC_TIMER value")?)
1069 }
1070 IFLA_BR_MCAST_LAST_MEMBER_INTVL => MulticastLastMemberInterval(
1071 parse_u64(payload).context("invalid IFLA_BR_MCAST_LAST_MEMBER_INTVL value")?,
1072 ),
1073 IFLA_BR_MCAST_MEMBERSHIP_INTVL => MulticastMembershipInterval(
1074 parse_u64(payload).context("invalid IFLA_BR_MCAST_MEMBERSHIP_INTVL value")?,
1075 ),
1076 IFLA_BR_MCAST_QUERIER_INTVL => MulticastQuerierInterval(
1077 parse_u64(payload).context("invalid IFLA_BR_MCAST_QUERIER_INTVL value")?,
1078 ),
1079 IFLA_BR_MCAST_QUERY_INTVL => MulticastQueryInterval(
1080 parse_u64(payload).context("invalid IFLA_BR_MCAST_QUERY_INTVL value")?,
1081 ),
1082 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL => MulticastQueryResponseInterval(
1083 parse_u64(payload).context("invalid IFLA_BR_MCAST_QUERY_RESPONSE_INTVL value")?,
1084 ),
1085 IFLA_BR_MCAST_STARTUP_QUERY_INTVL => MulticastStartupQueryInterval(
1086 parse_u64(payload).context("invalid IFLA_BR_MCAST_STARTUP_QUERY_INTVL value")?,
1087 ),
1088 IFLA_BR_FORWARD_DELAY => {
1089 ForwardDelay(parse_u32(payload).context("invalid IFLA_BR_FORWARD_DELAY value")?)
1090 }
1091 IFLA_BR_HELLO_TIME => {
1092 HelloTime(parse_u32(payload).context("invalid IFLA_BR_HELLO_TIME value")?)
1093 }
1094 IFLA_BR_MAX_AGE => MaxAge(parse_u32(payload).context("invalid IFLA_BR_MAX_AGE value")?),
1095 IFLA_BR_AGEING_TIME => {
1096 AgeingTime(parse_u32(payload).context("invalid IFLA_BR_AGEING_TIME value")?)
1097 }
1098 IFLA_BR_STP_STATE => {
1099 StpState(parse_u32(payload).context("invalid IFLA_BR_STP_STATE value")?)
1100 }
1101 IFLA_BR_MCAST_HASH_ELASTICITY => MulticastHashElasticity(
1102 parse_u32(payload).context("invalid IFLA_BR_MCAST_HASH_ELASTICITY value")?,
1103 ),
1104 IFLA_BR_MCAST_HASH_MAX => MulticastHashMax(
1105 parse_u32(payload).context("invalid IFLA_BR_MCAST_HASH_MAX value")?,
1106 ),
1107 IFLA_BR_MCAST_LAST_MEMBER_CNT => MulticastLastMemberCount(
1108 parse_u32(payload).context("invalid IFLA_BR_MCAST_LAST_MEMBER_CNT value")?,
1109 ),
1110 IFLA_BR_MCAST_STARTUP_QUERY_CNT => MulticastStartupQueryCount(
1111 parse_u32(payload).context("invalid IFLA_BR_MCAST_STARTUP_QUERY_CNT value")?,
1112 ),
1113 IFLA_BR_ROOT_PATH_COST => {
1114 RootPathCost(parse_u32(payload).context("invalid IFLA_BR_ROOT_PATH_COST value")?)
1115 }
1116 IFLA_BR_PRIORITY => {
1117 Priority(parse_u16(payload).context("invalid IFLA_BR_PRIORITY value")?)
1118 }
1119 IFLA_BR_VLAN_PROTOCOL => {
1120 VlanProtocol(parse_u16_be(payload).context("invalid IFLA_BR_VLAN_PROTOCOL value")?)
1121 }
1122 IFLA_BR_GROUP_FWD_MASK => {
1123 GroupFwdMask(parse_u16(payload).context("invalid IFLA_BR_GROUP_FWD_MASK value")?)
1124 }
1125 IFLA_BR_ROOT_ID | IFLA_BR_BRIDGE_ID => {
1126 if payload.len() != 8 {
1127 return Err("invalid IFLA_BR_ROOT_ID or IFLA_BR_BRIDGE_ID value".into());
1128 }
1129
1130 let priority = NativeEndian::read_u16(&payload[..2]);
1131 let address = parse_mac(&payload[2..])
1132 .context("invalid IFLA_BR_ROOT_ID or IFLA_BR_BRIDGE_ID value")?;
1133
1134 match buf.kind() {
1135 IFLA_BR_ROOT_ID => RootId((priority, address)),
1136 IFLA_BR_BRIDGE_ID => BridgeId((priority, address)),
1137 _ => unreachable!(),
1138 }
1139 }
1140 IFLA_BR_GROUP_ADDR => {
1141 GroupAddr(parse_mac(payload).context("invalid IFLA_BR_GROUP_ADDR value")?)
1142 }
1143 IFLA_BR_ROOT_PORT => {
1144 RootPort(parse_u16(payload).context("invalid IFLA_BR_ROOT_PORT value")?)
1145 }
1146 IFLA_BR_VLAN_DEFAULT_PVID => VlanDefaultPvid(
1147 parse_u16(payload).context("invalid IFLA_BR_VLAN_DEFAULT_PVID value")?,
1148 ),
1149 IFLA_BR_VLAN_FILTERING => {
1150 VlanFiltering(parse_u8(payload).context("invalid IFLA_BR_VLAN_FILTERING value")?)
1151 }
1152 IFLA_BR_TOPOLOGY_CHANGE => {
1153 TopologyChange(parse_u8(payload).context("invalid IFLA_BR_TOPOLOGY_CHANGE value")?)
1154 }
1155 IFLA_BR_TOPOLOGY_CHANGE_DETECTED => TopologyChangeDetected(
1156 parse_u8(payload).context("invalid IFLA_BR_TOPOLOGY_CHANGE_DETECTED value")?,
1157 ),
1158 IFLA_BR_MCAST_ROUTER => {
1159 MulticastRouter(parse_u8(payload).context("invalid IFLA_BR_MCAST_ROUTER value")?)
1160 }
1161 IFLA_BR_MCAST_SNOOPING => MulticastSnooping(
1162 parse_u8(payload).context("invalid IFLA_BR_MCAST_SNOOPING value")?,
1163 ),
1164 IFLA_BR_MCAST_QUERY_USE_IFADDR => MulticastQueryUseIfaddr(
1165 parse_u8(payload).context("invalid IFLA_BR_MCAST_QUERY_USE_IFADDR value")?,
1166 ),
1167 IFLA_BR_MCAST_QUERIER => {
1168 MulticastQuerier(parse_u8(payload).context("invalid IFLA_BR_MCAST_QUERIER value")?)
1169 }
1170 IFLA_BR_NF_CALL_IPTABLES => {
1171 NfCallIpTables(parse_u8(payload).context("invalid IFLA_BR_NF_CALL_IPTABLES value")?)
1172 }
1173 IFLA_BR_NF_CALL_IP6TABLES => NfCallIp6Tables(
1174 parse_u8(payload).context("invalid IFLA_BR_NF_CALL_IP6TABLES value")?,
1175 ),
1176 IFLA_BR_NF_CALL_ARPTABLES => NfCallArpTables(
1177 parse_u8(payload).context("invalid IFLA_BR_NF_CALL_ARPTABLES value")?,
1178 ),
1179 IFLA_BR_VLAN_STATS_ENABLED => VlanStatsEnabled(
1180 parse_u8(payload).context("invalid IFLA_BR_VLAN_STATS_ENABLED value")?,
1181 ),
1182 IFLA_BR_MCAST_STATS_ENABLED => MulticastStatsEnabled(
1183 parse_u8(payload).context("invalid IFLA_BR_MCAST_STATS_ENABLED value")?,
1184 ),
1185 IFLA_BR_MCAST_IGMP_VERSION => MulticastIgmpVersion(
1186 parse_u8(payload).context("invalid IFLA_BR_MCAST_IGMP_VERSION value")?,
1187 ),
1188 IFLA_BR_MCAST_MLD_VERSION => MulticastMldVersion(
1189 parse_u8(payload).context("invalid IFLA_BR_MCAST_MLD_VERSION value")?,
1190 ),
1191 IFLA_BR_VLAN_STATS_PER_PORT => VlanStatsPerHost(
1192 parse_u8(payload).context("invalid IFLA_BR_VLAN_STATS_PER_PORT value")?,
1193 ),
1194 IFLA_BR_MULTI_BOOLOPT => {
1195 MultiBoolOpt(parse_u64(payload).context("invalid IFLA_BR_MULTI_BOOLOPT value")?)
1196 }
1197 _ => Other(
1198 DefaultNla::parse(buf)
1199 .context("invalid link info bridge NLA value (unknown type)")?,
1200 ),
1201 })
1202 }
1203}
1204
1205#[derive(Debug, PartialEq, Eq, Clone)]
1206pub enum InfoIpoib {
1207 Unspec(Vec<u8>),
1208 Pkey(u16),
1209 Mode(u16),
1210 UmCast(u16),
1211 Other(DefaultNla),
1212}
1213
1214impl Nla for InfoIpoib {
1215 fn value_len(&self) -> usize {
1216 use self::InfoIpoib::*;
1217 match self {
1218 Unspec(bytes) => bytes.len(),
1219 Pkey(_) | Mode(_) | UmCast(_) => 2,
1220 Other(nla) => nla.value_len(),
1221 }
1222 }
1223
1224 fn emit_value(&self, buffer: &mut [u8]) {
1225 use self::InfoIpoib::*;
1226 match self {
1227 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1228 Pkey(value) => NativeEndian::write_u16(buffer, *value),
1229 Mode(value) => NativeEndian::write_u16(buffer, *value),
1230 UmCast(value) => NativeEndian::write_u16(buffer, *value),
1231 Other(nla) => nla.emit_value(buffer),
1232 }
1233 }
1234
1235 fn kind(&self) -> u16 {
1236 use self::InfoIpoib::*;
1237 match self {
1238 Unspec(_) => IFLA_IPOIB_UNSPEC,
1239 Pkey(_) => IFLA_IPOIB_PKEY,
1240 Mode(_) => IFLA_IPOIB_MODE,
1241 UmCast(_) => IFLA_IPOIB_UMCAST,
1242 Other(nla) => nla.kind(),
1243 }
1244 }
1245}
1246
1247impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpoib {
1248 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1249 use self::InfoIpoib::*;
1250 let payload = buf.value();
1251 Ok(match buf.kind() {
1252 IFLA_IPOIB_UNSPEC => Unspec(payload.to_vec()),
1253 IFLA_IPOIB_PKEY => Pkey(parse_u16(payload).context("invalid IFLA_IPOIB_PKEY value")?),
1254 IFLA_IPOIB_MODE => Mode(parse_u16(payload).context("invalid IFLA_IPOIB_MODE value")?),
1255 IFLA_IPOIB_UMCAST => {
1256 UmCast(parse_u16(payload).context("invalid IFLA_IPOIB_UMCAST value")?)
1257 }
1258 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1259 })
1260 }
1261}
1262
1263#[derive(Debug, PartialEq, Eq, Clone)]
1264pub enum VethInfo {
1265 Unspec(Vec<u8>),
1266 Peer(LinkMessage),
1267 Other(DefaultNla),
1268}
1269
1270impl Nla for VethInfo {
1271 fn value_len(&self) -> usize {
1272 use self::VethInfo::*;
1273 match *self {
1274 Unspec(ref bytes) => bytes.len(),
1275 Peer(ref message) => message.buffer_len(),
1276 Other(ref attr) => attr.value_len(),
1277 }
1278 }
1279
1280 fn emit_value(&self, buffer: &mut [u8]) {
1281 use self::VethInfo::*;
1282 match *self {
1283 Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
1284 Peer(ref message) => message.emit(buffer),
1285 Other(ref attr) => attr.emit_value(buffer),
1286 }
1287 }
1288
1289 fn kind(&self) -> u16 {
1290 use self::VethInfo::*;
1291 match *self {
1292 Unspec(_) => VETH_INFO_UNSPEC,
1293 Peer(_) => VETH_INFO_PEER,
1294 Other(ref attr) => attr.kind(),
1295 }
1296 }
1297}
1298
1299impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VethInfo {
1300 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1301 use self::VethInfo::*;
1302 let payload = buf.value();
1303 Ok(match buf.kind() {
1304 VETH_INFO_UNSPEC => Unspec(payload.to_vec()),
1305 VETH_INFO_PEER => {
1306 let err = "failed to parse veth link info";
1307 let buffer = LinkMessageBuffer::new_checked(&payload).context(err)?;
1308 Peer(LinkMessage::parse(&buffer).context(err)?)
1309 }
1310 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1311 })
1312 }
1313}
1314
1315#[derive(Debug, PartialEq, Eq, Clone)]
1316pub enum InfoIpVlan {
1317 Unspec(Vec<u8>),
1318 Mode(u16),
1319 Flags(u16),
1320 Other(DefaultNla),
1321}
1322
1323impl Nla for InfoIpVlan {
1324 fn value_len(&self) -> usize {
1325 use self::InfoIpVlan::*;
1326 match self {
1327 Unspec(bytes) => bytes.len(),
1328 Mode(_) | Flags(_) => 2,
1329 Other(nla) => nla.value_len(),
1330 }
1331 }
1332
1333 fn emit_value(&self, buffer: &mut [u8]) {
1334 use self::InfoIpVlan::*;
1335 match self {
1336 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1337 Mode(value) => NativeEndian::write_u16(buffer, *value),
1338 Flags(value) => NativeEndian::write_u16(buffer, *value),
1339 Other(nla) => nla.emit_value(buffer),
1340 }
1341 }
1342
1343 fn kind(&self) -> u16 {
1344 use self::InfoIpVlan::*;
1345 match self {
1346 Unspec(_) => IFLA_IPVLAN_UNSPEC,
1347 Mode(_) => IFLA_IPVLAN_MODE,
1348 Flags(_) => IFLA_IPVLAN_FLAGS,
1349 Other(nla) => nla.kind(),
1350 }
1351 }
1352}
1353
1354impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVlan {
1355 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1356 use self::InfoIpVlan::*;
1357 let payload = buf.value();
1358 Ok(match buf.kind() {
1359 IFLA_IPVLAN_UNSPEC => Unspec(payload.to_vec()),
1360 IFLA_IPVLAN_MODE => Mode(parse_u16(payload).context("invalid IFLA_IPVLAN_MODE value")?),
1361 IFLA_IPVLAN_FLAGS => {
1362 Flags(parse_u16(payload).context("invalid IFLA_IPVLAN_FLAGS value")?)
1363 }
1364 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1365 })
1366 }
1367}
1368
1369#[derive(Debug, PartialEq, Eq, Clone)]
1370pub enum InfoVrf {
1371 TableId(u32),
1372 Other(DefaultNla),
1373}
1374
1375impl Nla for InfoVrf {
1376 fn value_len(&self) -> usize {
1377 use self::InfoVrf::*;
1378 match self {
1379 TableId(_) => 4,
1380 Other(nla) => nla.value_len(),
1381 }
1382 }
1383
1384 fn emit_value(&self, buffer: &mut [u8]) {
1385 use self::InfoVrf::*;
1386 match self {
1387 TableId(value) => NativeEndian::write_u32(buffer, *value),
1388 Other(nla) => nla.emit_value(buffer),
1389 }
1390 }
1391
1392 fn kind(&self) -> u16 {
1393 use self::InfoVrf::*;
1394 match self {
1395 TableId(_) => IFLA_VRF_TABLE,
1396 Other(nla) => nla.kind(),
1397 }
1398 }
1399}
1400
1401impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVrf {
1402 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1403 use self::InfoVrf::*;
1404 let payload = buf.value();
1405 Ok(match buf.kind() {
1406 IFLA_VRF_TABLE => TableId(parse_u32(payload).context("invalid IFLA_VRF_TABLE value")?),
1407 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1408 })
1409 }
1410}
1411
1412#[derive(Debug, PartialEq, Eq, Clone)]
1413pub enum InfoMacVlan {
1414 Unspec(Vec<u8>),
1415 Mode(u32),
1416 Flags(u16),
1417 MacAddrMode(u32),
1418 MacAddr([u8; 6]),
1419 MacAddrData(Vec<InfoMacVlan>),
1420 MacAddrCount(u32),
1421 Other(DefaultNla),
1422}
1423
1424impl Nla for InfoMacVlan {
1425 fn value_len(&self) -> usize {
1426 use self::InfoMacVlan::*;
1427 match self {
1428 Unspec(bytes) => bytes.len(),
1429 Mode(_) => 4,
1430 Flags(_) => 2,
1431 MacAddrMode(_) => 4,
1432 MacAddr(_) => 6,
1433 MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
1434 MacAddrCount(_) => 4,
1435 Other(nla) => nla.value_len(),
1436 }
1437 }
1438
1439 fn emit_value(&self, buffer: &mut [u8]) {
1440 use self::InfoMacVlan::*;
1441 match self {
1442 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1443 Mode(value) => NativeEndian::write_u32(buffer, *value),
1444 Flags(value) => NativeEndian::write_u16(buffer, *value),
1445 MacAddrMode(value) => NativeEndian::write_u32(buffer, *value),
1446 MacAddr(bytes) => buffer.copy_from_slice(bytes),
1447 MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
1448 MacAddrCount(value) => NativeEndian::write_u32(buffer, *value),
1449 Other(nla) => nla.emit_value(buffer),
1450 }
1451 }
1452
1453 fn kind(&self) -> u16 {
1454 use self::InfoMacVlan::*;
1455 match self {
1456 Unspec(_) => IFLA_MACVLAN_UNSPEC,
1457 Mode(_) => IFLA_MACVLAN_MODE,
1458 Flags(_) => IFLA_MACVLAN_FLAGS,
1459 MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
1460 MacAddr(_) => IFLA_MACVLAN_MACADDR,
1461 MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
1462 MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
1463 Other(nla) => nla.kind(),
1464 }
1465 }
1466}
1467
1468impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVlan {
1469 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1470 use self::InfoMacVlan::*;
1471 let payload = buf.value();
1472 Ok(match buf.kind() {
1473 IFLA_MACVLAN_UNSPEC => Unspec(payload.to_vec()),
1474 IFLA_MACVLAN_MODE => {
1475 Mode(parse_u32(payload).context("invalid IFLA_MACVLAN_MODE value")?)
1476 }
1477 IFLA_MACVLAN_FLAGS => {
1478 Flags(parse_u16(payload).context("invalid IFLA_MACVLAN_FLAGS value")?)
1479 }
1480 IFLA_MACVLAN_MACADDR_MODE => {
1481 MacAddrMode(parse_u32(payload).context("invalid IFLA_MACVLAN_MACADDR_MODE value")?)
1482 }
1483 IFLA_MACVLAN_MACADDR => {
1484 MacAddr(parse_mac(payload).context("invalid IFLA_MACVLAN_MACADDR value")?)
1485 }
1486 IFLA_MACVLAN_MACADDR_DATA => {
1487 let mut mac_data = Vec::new();
1488 let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
1489 for nla in NlasIterator::new(payload) {
1490 let nla = &nla.context(err)?;
1491 let parsed = InfoMacVlan::parse(nla).context(err)?;
1492 mac_data.push(parsed);
1493 }
1494 MacAddrData(mac_data)
1495 }
1496 IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
1497 parse_u32(payload).context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
1498 ),
1499 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1500 })
1501 }
1502}
1503
1504#[derive(Debug, PartialEq, Eq, Clone)]
1505pub enum InfoMacVtap {
1506 Unspec(Vec<u8>),
1507 Mode(u32),
1508 Flags(u16),
1509 MacAddrMode(u32),
1510 MacAddr([u8; 6]),
1511 MacAddrData(Vec<InfoMacVtap>),
1512 MacAddrCount(u32),
1513 Other(DefaultNla),
1514}
1515
1516impl Nla for InfoMacVtap {
1517 fn value_len(&self) -> usize {
1518 use self::InfoMacVtap::*;
1519 match self {
1520 Unspec(bytes) => bytes.len(),
1521 Mode(_) => 4,
1522 Flags(_) => 2,
1523 MacAddrMode(_) => 4,
1524 MacAddr(_) => 6,
1525 MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
1526 MacAddrCount(_) => 4,
1527 Other(nla) => nla.value_len(),
1528 }
1529 }
1530
1531 fn emit_value(&self, buffer: &mut [u8]) {
1532 use self::InfoMacVtap::*;
1533 match self {
1534 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1535 Mode(value) => NativeEndian::write_u32(buffer, *value),
1536 Flags(value) => NativeEndian::write_u16(buffer, *value),
1537 MacAddrMode(value) => NativeEndian::write_u32(buffer, *value),
1538 MacAddr(bytes) => buffer.copy_from_slice(bytes),
1539 MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
1540 MacAddrCount(value) => NativeEndian::write_u32(buffer, *value),
1541 Other(nla) => nla.emit_value(buffer),
1542 }
1543 }
1544
1545 fn kind(&self) -> u16 {
1546 use self::InfoMacVtap::*;
1547 match self {
1548 Unspec(_) => IFLA_MACVLAN_UNSPEC,
1549 Mode(_) => IFLA_MACVLAN_MODE,
1550 Flags(_) => IFLA_MACVLAN_FLAGS,
1551 MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
1552 MacAddr(_) => IFLA_MACVLAN_MACADDR,
1553 MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
1554 MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
1555 Other(nla) => nla.kind(),
1556 }
1557 }
1558}
1559
1560impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
1561 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1562 use self::InfoMacVtap::*;
1563 let payload = buf.value();
1564 Ok(match buf.kind() {
1565 IFLA_MACVLAN_UNSPEC => Unspec(payload.to_vec()),
1566 IFLA_MACVLAN_MODE => {
1567 Mode(parse_u32(payload).context("invalid IFLA_MACVLAN_MODE value")?)
1568 }
1569 IFLA_MACVLAN_FLAGS => {
1570 Flags(parse_u16(payload).context("invalid IFLA_MACVLAN_FLAGS value")?)
1571 }
1572 IFLA_MACVLAN_MACADDR_MODE => {
1573 MacAddrMode(parse_u32(payload).context("invalid IFLA_MACVLAN_MACADDR_MODE value")?)
1574 }
1575 IFLA_MACVLAN_MACADDR => {
1576 MacAddr(parse_mac(payload).context("invalid IFLA_MACVLAN_MACADDR value")?)
1577 }
1578 IFLA_MACVLAN_MACADDR_DATA => {
1579 let mut mac_data = Vec::new();
1580 let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
1581 for nla in NlasIterator::new(payload) {
1582 let nla = &nla.context(err)?;
1583 let parsed = InfoMacVtap::parse(nla).context(err)?;
1584 mac_data.push(parsed);
1585 }
1586 MacAddrData(mac_data)
1587 }
1588 IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
1589 parse_u32(payload).context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
1590 ),
1591 kind => Other(DefaultNla::parse(buf).context(format!("unknown NLA type {}", kind))?),
1592 })
1593 }
1594}
1595
1596#[cfg(test)]
1597mod tests {
1598 use super::*;
1599 use crate::{nlas::link::Nla, traits::Emitable, LinkHeader, LinkMessage};
1600
1601 #[rustfmt::skip]
1602 static BRIDGE: [u8; 424] = [
1603 0x0b, 0x00, 0x01, 0x00, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00, 0x9c, 0x01, 0x02, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x13, 0x00, 0xb5, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0xcf, 0x07, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x2f, 0x75, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x80, 0x00, 0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e, 0x0c, 0x00, 0x0a, 0x00, 0x80, 0x00, 0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x81, 0x00, 0x00, 0x00, 0x06, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x17, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x1e, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x8f, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x9b, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x21, 0x00, 0xd3, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x22, 0x00, 0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x23, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1811
1812 lazy_static! {
1813 static ref BRIDGE_INFO: Vec<InfoBridge> = vec![
1814 InfoBridge::HelloTimer(35),
1815 InfoBridge::TcnTimer(0),
1816 InfoBridge::TopologyChangeTimer(0),
1817 InfoBridge::GcTimer(14261),
1818 InfoBridge::ForwardDelay(199),
1819 InfoBridge::HelloTime(199),
1820 InfoBridge::MaxAge(1999),
1821 InfoBridge::AgeingTime(29999),
1822 InfoBridge::StpState(1),
1823 InfoBridge::Priority(0x8000),
1824 InfoBridge::VlanFiltering(0),
1825 InfoBridge::GroupFwdMask(0),
1826 InfoBridge::BridgeId((128, [0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e])),
1827 InfoBridge::RootId((128, [0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e])),
1828 InfoBridge::RootPort(0),
1829 InfoBridge::RootPathCost(0),
1830 InfoBridge::TopologyChange(0),
1831 InfoBridge::TopologyChangeDetected(0),
1832 InfoBridge::GroupAddr([0x01, 0x80, 0xc2, 0x00, 0x00, 0x00]),
1833 InfoBridge::VlanProtocol(33024),
1834 InfoBridge::VlanDefaultPvid(1),
1835 InfoBridge::VlanStatsEnabled(0),
1836 InfoBridge::MulticastRouter(1),
1837 InfoBridge::MulticastSnooping(1),
1838 InfoBridge::MulticastQueryUseIfaddr(0),
1839 InfoBridge::MulticastQuerier(0),
1840 InfoBridge::MulticastStatsEnabled(0),
1841 InfoBridge::MulticastHashElasticity(4),
1842 InfoBridge::MulticastHashMax(512),
1843 InfoBridge::MulticastLastMemberCount(2),
1844 InfoBridge::MulticastStartupQueryCount(2),
1845 InfoBridge::MulticastIgmpVersion(2),
1846 InfoBridge::MulticastMldVersion(1),
1847 InfoBridge::MulticastLastMemberInterval(99),
1848 InfoBridge::MulticastMembershipInterval(25999),
1849 InfoBridge::MulticastQuerierInterval(25499),
1850 InfoBridge::MulticastQueryInterval(12499),
1851 InfoBridge::MulticastQueryResponseInterval(999),
1852 InfoBridge::MulticastStartupQueryInterval(3124),
1853 InfoBridge::NfCallIpTables(0),
1854 InfoBridge::NfCallIp6Tables(0),
1855 InfoBridge::NfCallArpTables(0),
1856 InfoBridge::VlanStatsPerHost(1),
1857 InfoBridge::MultiBoolOpt(0),
1858 ];
1859 }
1860
1861 #[test]
1862 fn parse_info_kind() {
1863 let info_kind_nla = NlaBuffer::new_checked(&BRIDGE[..12]).unwrap();
1864 let parsed = InfoKind::parse(&info_kind_nla).unwrap();
1865 assert_eq!(parsed, InfoKind::Bridge);
1866 }
1867
1868 #[test]
1869 fn parse_info_bridge() {
1870 let nlas = NlasIterator::new(&BRIDGE[16..]);
1871 for nla in nlas.map(|nla| nla.unwrap()) {
1872 InfoBridge::parse(&nla).unwrap();
1873 }
1874 }
1875
1876 #[rustfmt::skip]
1877 #[test]
1878 fn parse_veth_info() {
1879 let data = vec![
1880 0x08, 0x00, 0x01, 0x00, 0x76, 0x65, 0x74, 0x68, 0x30, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x76, 0x65, 0x74, 0x68, 0x63, 0x30, 0x65, 0x36, 0x30, 0x64, 0x36, 0x00,
1900 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
1904 ];
1905 let nla = NlaBuffer::new_checked(&data[..]).unwrap();
1906 let parsed = VecInfo::parse(&nla).unwrap().0;
1907 let expected = vec![
1908 Info::Kind(InfoKind::Veth),
1909 Info::Data(InfoData::Veth(VethInfo::Peer(LinkMessage {
1910 header: LinkHeader {
1911 interface_family: 0,
1912 index: 0,
1913 link_layer_type: ARPHRD_NETROM,
1914 flags: 0,
1915 change_mask: 0,
1916 },
1917 nlas: vec![
1918 Nla::IfName("vethc0e60d6".to_string()),
1919 Nla::TxQueueLen(0),
1920 ],
1921 }))),
1922 ];
1923 assert_eq!(expected, parsed);
1924 }
1925
1926 #[rustfmt::skip]
1927 static IPVLAN: [u8; 32] = [
1928 0x0b, 0x00, 0x01, 0x00, 0x69, 0x70, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, ];
1945
1946 lazy_static! {
1947 static ref IPVLAN_INFO: Vec<InfoIpVlan> = vec![
1948 InfoIpVlan::Mode(1), InfoIpVlan::Flags(2), ];
1951 }
1952
1953 #[test]
1954 fn parse_info_ipvlan() {
1955 let nla = NlaBuffer::new_checked(&IPVLAN[..]).unwrap();
1956 let parsed = VecInfo::parse(&nla).unwrap().0;
1957 let expected = vec![
1958 Info::Kind(InfoKind::IpVlan),
1959 Info::Data(InfoData::IpVlan(IPVLAN_INFO.clone())),
1960 ];
1961 assert_eq!(expected, parsed);
1962 }
1963
1964 #[test]
1965 fn emit_info_ipvlan() {
1966 let nlas = vec![
1967 Info::Kind(InfoKind::IpVlan),
1968 Info::Data(InfoData::IpVlan(IPVLAN_INFO.clone())),
1969 ];
1970
1971 assert_eq!(nlas.as_slice().buffer_len(), 32);
1972
1973 let mut vec = vec![0xff; 32];
1974 nlas.as_slice().emit(&mut vec);
1975 assert_eq!(&vec[..], &IPVLAN[..]);
1976 }
1977
1978 #[rustfmt::skip]
1979 static MACVLAN: [u8; 24] = [
1980 0x0c, 0x00, 0x01, 0x00, 0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, ];
1989
1990 lazy_static! {
1991 static ref MACVLAN_INFO: Vec<InfoMacVlan> = vec![
1992 InfoMacVlan::Mode(4), ];
1994 }
1995
1996 #[test]
1997 fn parse_info_macvlan() {
1998 let nla = NlaBuffer::new_checked(&MACVLAN[..]).unwrap();
1999 let parsed = VecInfo::parse(&nla).unwrap().0;
2000 let expected = vec![
2001 Info::Kind(InfoKind::MacVlan),
2002 Info::Data(InfoData::MacVlan(MACVLAN_INFO.clone())),
2003 ];
2004 assert_eq!(expected, parsed);
2005 }
2006
2007 #[test]
2008 fn emit_info_macvlan() {
2009 let nlas = vec![
2010 Info::Kind(InfoKind::MacVlan),
2011 Info::Data(InfoData::MacVlan(MACVLAN_INFO.clone())),
2012 ];
2013
2014 assert_eq!(nlas.as_slice().buffer_len(), 24);
2015
2016 let mut vec = vec![0xff; 24];
2017 nlas.as_slice().emit(&mut vec);
2018 assert_eq!(&vec[..], &MACVLAN[..]);
2019 }
2020
2021 #[rustfmt::skip]
2022 static MACVLAN_SOURCE_SET: [u8; 84] = [
2023 0x0c, 0x00, 0x01, 0x00, 0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x48, 0x00, 0x02, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x22, 0xf5, 0x54, 0x09, 0x88, 0xd7, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x22, 0xf5, 0x54, 0x09, 0x99, 0x32, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x22, 0xf5, 0x54, 0x09, 0x87, 0x45, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x22, 0xf5, 0x54, 0x09, 0x11, 0x45, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, ];
2057
2058 lazy_static! {
2059 static ref MACVLAN_SOURCE_SET_INFO: Vec<InfoMacVlan> = vec![
2060 InfoMacVlan::MacAddrMode(3), InfoMacVlan::MacAddrData(vec![
2062 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x88, 0xd7,]),
2063 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x99, 0x32,]),
2064 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x87, 0x45,]),
2065 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x11, 0x45,]),
2066 ]),
2067 InfoMacVlan::Mode(16), ];
2069 }
2070
2071 #[test]
2072 fn parse_info_macvlan_source_set() {
2073 let nla = NlaBuffer::new_checked(&MACVLAN_SOURCE_SET[..]).unwrap();
2074 let parsed = VecInfo::parse(&nla).unwrap().0;
2075 let expected = vec![
2076 Info::Kind(InfoKind::MacVlan),
2077 Info::Data(InfoData::MacVlan(MACVLAN_SOURCE_SET_INFO.clone())),
2078 ];
2079 assert_eq!(expected, parsed);
2080 }
2081
2082 #[test]
2083 fn emit_info_macvlan_source_set() {
2084 let nlas = vec![
2085 Info::Kind(InfoKind::MacVlan),
2086 Info::Data(InfoData::MacVlan(MACVLAN_SOURCE_SET_INFO.clone())),
2087 ];
2088
2089 assert_eq!(nlas.as_slice().buffer_len(), 84);
2090
2091 let mut vec = vec![0xff; 84];
2092 nlas.as_slice().emit(&mut vec);
2093 assert_eq!(&vec[..], &MACVLAN_SOURCE_SET[..]);
2094 }
2095
2096 #[test]
2097 fn parse() {
2098 let nla = NlaBuffer::new_checked(&BRIDGE[..]).unwrap();
2099 let parsed = VecInfo::parse(&nla).unwrap().0;
2100 assert_eq!(parsed.len(), 2);
2101 assert_eq!(parsed[0], Info::Kind(InfoKind::Bridge));
2102 if let Info::Data(InfoData::Bridge(nlas)) = parsed[1].clone() {
2103 assert_eq!(nlas.len(), BRIDGE_INFO.len());
2104 for (expected, parsed) in BRIDGE_INFO.iter().zip(nlas) {
2105 assert_eq!(*expected, parsed);
2106 }
2107 } else {
2108 panic!(
2109 "expected Info::Data(InfoData::Bridge(_) got {:?}",
2110 parsed[1]
2111 )
2112 }
2113 }
2114
2115 #[test]
2116 fn emit() {
2117 let nlas = vec![
2118 Info::Kind(InfoKind::Bridge),
2119 Info::Data(InfoData::Bridge(BRIDGE_INFO.clone())),
2120 ];
2121
2122 assert_eq!(nlas.as_slice().buffer_len(), 424);
2123
2124 let mut vec = vec![0xff; 424];
2125 nlas.as_slice().emit(&mut vec);
2126 assert_eq!(&vec[..], &BRIDGE[..]);
2127 }
2128}