1use anyhow::Context;
4use byteorder::{BigEndian, ByteOrder, NativeEndian};
5use netlink_packet_utils::{
6 nla::{DefaultNla, Nla, NlaBuffer, NlasIterator},
7 parsers::{
8 parse_i32, parse_mac, parse_string, parse_u16, parse_u16_be, parse_u32,
9 parse_u64, parse_u8,
10 },
11 traits::{Emitable, Parseable},
12 DecodeError,
13};
14
15use super::{bond::InfoBond, bond_port::InfoBondPort, bridge::InfoBridge};
16use crate::{constants::*, LinkMessage, LinkMessageBuffer};
17
18const DUMMY: &str = "dummy";
19const IFB: &str = "ifb";
20const BRIDGE: &str = "bridge";
21const TUN: &str = "tun";
22const NLMON: &str = "nlmon";
23const VLAN: &str = "vlan";
24const VETH: &str = "veth";
25const VXLAN: &str = "vxlan";
26const BOND: &str = "bond";
27const IPVLAN: &str = "ipvlan";
28const MACVLAN: &str = "macvlan";
29const MACVTAP: &str = "macvtap";
30const GRETAP: &str = "gretap";
31const IP6GRETAP: &str = "ip6gretap";
32const IPIP: &str = "ipip";
33const SIT: &str = "sit";
34const GRE: &str = "gre";
35const IP6GRE: &str = "ip6gre";
36const VTI: &str = "vti";
37const VRF: &str = "vrf";
38const GTP: &str = "gtp";
39const IPOIB: &str = "ipoib";
40const WIREGUARD: &str = "wireguard";
41const XFRM: &str = "xfrm";
42const MACSEC: &str = "macsec";
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45#[non_exhaustive]
46pub enum Info {
47 Unspec(Vec<u8>),
48 Xstats(Vec<u8>),
49 Kind(InfoKind),
50 Data(InfoData),
51 PortKind(InfoPortKind),
52 PortData(InfoPortData),
53}
54
55impl Nla for Info {
56 #[rustfmt::skip]
57 fn value_len(&self) -> usize {
58 use self::Info::*;
59 match self {
60 Unspec(ref bytes)
61 | Xstats(ref bytes)
62 => bytes.len(),
63 Kind(ref nla) => nla.value_len(),
64 Data(ref nla) => nla.value_len(),
65 PortKind(ref nla) => nla.value_len(),
66 PortData(ref nla) => nla.value_len(),
67 }
68 }
69
70 #[rustfmt::skip]
71 fn emit_value(&self, buffer: &mut [u8]) {
72 use self::Info::*;
73 match self {
74 Unspec(ref bytes)
75 | Xstats(ref bytes)
76 => buffer.copy_from_slice(bytes),
77 Kind(ref nla) => nla.emit_value(buffer),
78 Data(ref nla) => nla.emit_value(buffer),
79 PortKind(ref nla) => nla.emit_value(buffer),
80 PortData(ref nla) => nla.emit_value(buffer),
81 }
82 }
83
84 fn kind(&self) -> u16 {
85 use self::Info::*;
86 match self {
87 Unspec(_) => IFLA_INFO_UNSPEC,
88 Xstats(_) => IFLA_INFO_XSTATS,
89 PortKind(_) => IFLA_INFO_PORT_KIND,
90 PortData(_) => IFLA_INFO_PORT_DATA,
91 Kind(_) => IFLA_INFO_KIND,
92 Data(_) => IFLA_INFO_DATA,
93 }
94 }
95}
96
97pub(crate) struct VecInfo(pub(crate) Vec<Info>);
98
99impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VecInfo {
110 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
111 let mut res = Vec::new();
112 let nlas = NlasIterator::new(buf.into_inner());
113 let mut link_info_kind: Option<InfoKind> = None;
114 let mut link_info_port_kind: Option<InfoPortKind> = None;
115 for nla in nlas {
116 let nla = nla?;
117 match nla.kind() {
118 IFLA_INFO_UNSPEC => {
119 res.push(Info::Unspec(nla.value().to_vec()))
120 }
121 IFLA_INFO_XSTATS => {
122 res.push(Info::Xstats(nla.value().to_vec()))
123 }
124 IFLA_INFO_PORT_KIND => {
125 let parsed = InfoPortKind::parse(&nla)?;
126 res.push(Info::PortKind(parsed.clone()));
127 link_info_port_kind = Some(parsed);
128 }
129 IFLA_INFO_PORT_DATA => {
130 if let Some(link_info_port_kind) = link_info_port_kind {
131 let payload = nla.value();
132 let info_port_data = match link_info_port_kind {
133 InfoPortKind::Bond => {
134 let mut v = Vec::new();
135 let err =
136 "failed to parse IFLA_INFO_PORT_DATA (IFLA_INFO_PORT_KIND is 'bond')";
137 for nla in NlasIterator::new(payload) {
138 let nla = &nla.context(err)?;
139 let parsed = InfoBondPort::parse(nla)
140 .context(err)?;
141 v.push(parsed);
142 }
143 InfoPortData::BondPort(v)
144 }
145 InfoPortKind::Other(_) => {
146 InfoPortData::Other(payload.to_vec())
147 }
148 };
149 res.push(Info::PortData(info_port_data));
150 } else {
151 return Err("IFLA_INFO_PORT_DATA is not preceded by an IFLA_INFO_PORT_KIND".into());
152 }
153 link_info_port_kind = None;
154 }
155 IFLA_INFO_KIND => {
156 let parsed = InfoKind::parse(&nla)?;
157 res.push(Info::Kind(parsed.clone()));
158 link_info_kind = Some(parsed);
159 }
160 IFLA_INFO_DATA => {
161 if let Some(link_info_kind) = link_info_kind {
162 let payload = nla.value();
163 let info_data = match link_info_kind {
164 InfoKind::Dummy => {
165 InfoData::Dummy(payload.to_vec())
166 }
167 InfoKind::Ifb => InfoData::Ifb(payload.to_vec()),
168 InfoKind::Bridge => {
169 let mut v = Vec::new();
170 let err =
171 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'bridge')";
172 for nla in NlasIterator::new(payload) {
173 let nla = &nla.context(err)?;
174 let parsed =
175 InfoBridge::parse(nla).context(err)?;
176 v.push(parsed);
177 }
178 InfoData::Bridge(v)
179 }
180 InfoKind::Vlan => {
181 let mut v = Vec::new();
182 let err =
183 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vlan')";
184 for nla in NlasIterator::new(payload) {
185 let nla = &nla.context(err)?;
186 let parsed =
187 InfoVlan::parse(nla).context(err)?;
188 v.push(parsed);
189 }
190 InfoData::Vlan(v)
191 }
192 InfoKind::Tun => InfoData::Tun(payload.to_vec()),
193 InfoKind::Nlmon => {
194 InfoData::Nlmon(payload.to_vec())
195 }
196 InfoKind::Veth => {
197 let err =
198 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'veth')";
199 let nla_buf = NlaBuffer::new_checked(&payload)
200 .context(err)?;
201 let parsed =
202 VethInfo::parse(&nla_buf).context(err)?;
203 InfoData::Veth(parsed)
204 }
205 InfoKind::Vxlan => {
206 let mut v = Vec::new();
207 let err =
208 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vxlan')";
209 for nla in NlasIterator::new(payload) {
210 let nla = &nla.context(err)?;
211 let parsed =
212 InfoVxlan::parse(nla).context(err)?;
213 v.push(parsed);
214 }
215 InfoData::Vxlan(v)
216 }
217 InfoKind::Bond => {
218 let mut v = Vec::new();
219 let err =
220 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'bond')";
221 for nla in NlasIterator::new(payload) {
222 let nla = &nla.context(err)?;
223 let parsed =
224 InfoBond::parse(nla).context(err)?;
225 v.push(parsed);
226 }
227 InfoData::Bond(v)
228 }
229 InfoKind::IpVlan => {
230 let mut v = Vec::new();
231 let err =
232 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'ipvlan')";
233 for nla in NlasIterator::new(payload) {
234 let nla = &nla.context(err)?;
235 let parsed =
236 InfoIpVlan::parse(nla).context(err)?;
237 v.push(parsed);
238 }
239 InfoData::IpVlan(v)
240 }
241 InfoKind::MacVlan => {
242 let mut v = Vec::new();
243 let err =
244 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'macvlan')";
245 for nla in NlasIterator::new(payload) {
246 let nla = &nla.context(err)?;
247 let parsed =
248 InfoMacVlan::parse(nla).context(err)?;
249 v.push(parsed);
250 }
251 InfoData::MacVlan(v)
252 }
253 InfoKind::MacVtap => {
254 let mut v = Vec::new();
255 let err =
256 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'macvtap')";
257 for nla in NlasIterator::new(payload) {
258 let nla = &nla.context(err)?;
259 let parsed =
260 InfoMacVtap::parse(nla).context(err)?;
261 v.push(parsed);
262 }
263 InfoData::MacVtap(v)
264 }
265 InfoKind::GreTap => {
266 InfoData::GreTap(payload.to_vec())
267 }
268 InfoKind::GreTap6 => {
269 InfoData::GreTap6(payload.to_vec())
270 }
271 InfoKind::IpTun => {
272 InfoData::IpTun(payload.to_vec())
273 }
274 InfoKind::SitTun => {
275 InfoData::SitTun(payload.to_vec())
276 }
277 InfoKind::GreTun => {
278 InfoData::GreTun(payload.to_vec())
279 }
280 InfoKind::GreTun6 => {
281 InfoData::GreTun6(payload.to_vec())
282 }
283 InfoKind::Vti => InfoData::Vti(payload.to_vec()),
284 InfoKind::Vrf => {
285 let mut v = Vec::new();
286 let err =
287 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'vrf')";
288 for nla in NlasIterator::new(payload) {
289 let nla = &nla.context(err)?;
290 let parsed =
291 InfoVrf::parse(nla).context(err)?;
292 v.push(parsed);
293 }
294 InfoData::Vrf(v)
295 }
296 InfoKind::Gtp => InfoData::Gtp(payload.to_vec()),
297 InfoKind::Ipoib => {
298 let mut v = Vec::new();
299 let err =
300 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'ipoib')";
301 for nla in NlasIterator::new(payload) {
302 let nla = &nla.context(err)?;
303 let parsed =
304 InfoIpoib::parse(nla).context(err)?;
305 v.push(parsed);
306 }
307 InfoData::Ipoib(v)
308 }
309 InfoKind::Wireguard => {
310 InfoData::Wireguard(payload.to_vec())
311 }
312 InfoKind::Other(_) => {
313 InfoData::Other(payload.to_vec())
314 }
315 InfoKind::Xfrm => {
316 let mut v = Vec::new();
317 let err =
318 "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'Xfrm')";
319 for nla in NlasIterator::new(payload) {
320 let nla = &nla.context(err)?;
321 let parsed =
322 InfoXfrmTun::parse(nla).context(err)?;
323 v.push(parsed);
324 }
325 InfoData::Xfrm(v)
326 }
327 InfoKind::MacSec => {
328 let mut v = Vec::new();
329 let err = "failed to parse IFLA_INFO_DATA (IFLA_INFO_KIND is 'macsec')";
330 for nla in NlasIterator::new(payload) {
331 let nla = &nla.context(err)?;
332 let parsed =
333 InfoMacSec::parse(nla).context(err)?;
334 v.push(parsed);
335 }
336 InfoData::MacSec(v)
337 }
338 };
339 res.push(Info::Data(info_data));
340 } else {
341 return Err("IFLA_INFO_DATA is not preceded by an IFLA_INFO_KIND".into());
342 }
343 link_info_kind = None;
344 }
345 _ => {
346 return Err(
347 format!("unknown NLA type {}", nla.kind()).into()
348 )
349 }
350 }
351 }
352 Ok(VecInfo(res))
353 }
354}
355
356#[derive(Debug, PartialEq, Eq, Clone)]
357#[non_exhaustive]
358pub enum InfoData {
359 Bridge(Vec<InfoBridge>),
360 Tun(Vec<u8>),
361 Nlmon(Vec<u8>),
362 Vlan(Vec<InfoVlan>),
363 Dummy(Vec<u8>),
364 Ifb(Vec<u8>),
365 Veth(VethInfo),
366 Vxlan(Vec<InfoVxlan>),
367 Bond(Vec<InfoBond>),
368 IpVlan(Vec<InfoIpVlan>),
369 MacVlan(Vec<InfoMacVlan>),
370 MacVtap(Vec<InfoMacVtap>),
371 GreTap(Vec<u8>),
372 GreTap6(Vec<u8>),
373 IpTun(Vec<u8>),
374 SitTun(Vec<u8>),
375 GreTun(Vec<u8>),
376 GreTun6(Vec<u8>),
377 Vti(Vec<u8>),
378 Vrf(Vec<InfoVrf>),
379 Gtp(Vec<u8>),
380 Ipoib(Vec<InfoIpoib>),
381 Wireguard(Vec<u8>),
382 Xfrm(Vec<InfoXfrmTun>),
383 MacSec(Vec<InfoMacSec>),
384 Other(Vec<u8>),
385}
386
387impl Nla for InfoData {
388 #[rustfmt::skip]
389 fn value_len(&self) -> usize {
390 use self::InfoData::*;
391 match self {
392 Bond(ref nlas) => nlas.as_slice().buffer_len(),
393 Bridge(ref nlas) => nlas.as_slice().buffer_len(),
394 Vlan(ref nlas) => nlas.as_slice().buffer_len(),
395 Veth(ref msg) => msg.buffer_len(),
396 IpVlan(ref nlas) => nlas.as_slice().buffer_len(),
397 Ipoib(ref nlas) => nlas.as_slice().buffer_len(),
398 MacVlan(ref nlas) => nlas.as_slice().buffer_len(),
399 MacVtap(ref nlas) => nlas.as_slice().buffer_len(),
400 Vrf(ref nlas) => nlas.as_slice().buffer_len(),
401 Vxlan(ref nlas) => nlas.as_slice().buffer_len(),
402 Xfrm(ref nlas) => nlas.as_slice().buffer_len(),
403 MacSec(ref nlas) => nlas.as_slice().buffer_len(),
404 Dummy(ref bytes)
405 | Tun(ref bytes)
406 | Nlmon(ref bytes)
407 | Ifb(ref bytes)
408 | GreTap(ref bytes)
409 | GreTap6(ref bytes)
410 | IpTun(ref bytes)
411 | SitTun(ref bytes)
412 | GreTun(ref bytes)
413 | GreTun6(ref bytes)
414 | Vti(ref bytes)
415 | Gtp(ref bytes)
416 | Wireguard(ref bytes)
417 | Other(ref bytes)
418 => bytes.len(),
419 }
420 }
421
422 #[rustfmt::skip]
423 fn emit_value(&self, buffer: &mut [u8]) {
424 use self::InfoData::*;
425 match self {
426 Bond(ref nlas) => nlas.as_slice().emit(buffer),
427 Bridge(ref nlas) => nlas.as_slice().emit(buffer),
428 Vlan(ref nlas) => nlas.as_slice().emit(buffer),
429 Veth(ref msg) => msg.emit(buffer),
430 IpVlan(ref nlas) => nlas.as_slice().emit(buffer),
431 Ipoib(ref nlas) => nlas.as_slice().emit(buffer),
432 MacVlan(ref nlas) => nlas.as_slice().emit(buffer),
433 MacVtap(ref nlas) => nlas.as_slice().emit(buffer),
434 Vrf(ref nlas) => nlas.as_slice().emit(buffer),
435 Vxlan(ref nlas) => nlas.as_slice().emit(buffer),
436 Xfrm(ref nlas) => nlas.as_slice().emit(buffer),
437 MacSec(ref nlas) => nlas.as_slice().emit(buffer),
438 Dummy(ref bytes)
439 | Tun(ref bytes)
440 | Nlmon(ref bytes)
441 | Ifb(ref bytes)
442 | GreTap(ref bytes)
443 | GreTap6(ref bytes)
444 | IpTun(ref bytes)
445 | SitTun(ref bytes)
446 | GreTun(ref bytes)
447 | GreTun6(ref bytes)
448 | Vti(ref bytes)
449 | Gtp(ref bytes)
450 | Wireguard(ref bytes)
451 | Other(ref bytes)
452 => buffer.copy_from_slice(bytes),
453 }
454 }
455
456 fn kind(&self) -> u16 {
457 IFLA_INFO_DATA
458 }
459}
460
461#[derive(Debug, PartialEq, Eq, Clone)]
462#[non_exhaustive]
463pub enum InfoPortData {
464 BondPort(Vec<InfoBondPort>),
465 Other(Vec<u8>),
466}
467
468impl Nla for InfoPortData {
469 #[rustfmt::skip]
470 fn value_len(&self) -> usize {
471 use self::InfoPortData::*;
472 match self {
473 BondPort(ref nlas) => nlas.as_slice().buffer_len(),
474 Other(ref bytes) => bytes.len(),
475 }
476 }
477
478 #[rustfmt::skip]
479 fn emit_value(&self, buffer: &mut [u8]) {
480 use self::InfoPortData::*;
481 match self {
482 BondPort(ref nlas) => nlas.as_slice().emit(buffer),
483 Other(ref bytes) => buffer.copy_from_slice(bytes),
484 }
485 }
486
487 fn kind(&self) -> u16 {
488 IFLA_INFO_PORT_DATA
489 }
490}
491
492#[derive(Debug, PartialEq, Eq, Clone)]
493#[non_exhaustive]
494pub enum InfoKind {
495 Dummy,
496 Ifb,
497 Bridge,
498 Tun,
499 Nlmon,
500 Vlan,
501 Veth,
502 Vxlan,
503 Bond,
504 IpVlan,
505 MacVlan,
506 MacVtap,
507 GreTap,
508 GreTap6,
509 IpTun,
510 SitTun,
511 GreTun,
512 GreTun6,
513 Vti,
514 Vrf,
515 Gtp,
516 Ipoib,
517 Wireguard,
518 Xfrm,
519 MacSec,
520 Other(String),
521}
522
523impl Nla for InfoKind {
524 fn value_len(&self) -> usize {
525 use self::InfoKind::*;
526 let len = match *self {
527 Dummy => DUMMY.len(),
528 Ifb => IFB.len(),
529 Bridge => BRIDGE.len(),
530 Tun => TUN.len(),
531 Nlmon => NLMON.len(),
532 Vlan => VLAN.len(),
533 Veth => VETH.len(),
534 Vxlan => VXLAN.len(),
535 Bond => BOND.len(),
536 IpVlan => IPVLAN.len(),
537 MacVlan => MACVLAN.len(),
538 MacVtap => MACVTAP.len(),
539 GreTap => GRETAP.len(),
540 GreTap6 => IP6GRETAP.len(),
541 IpTun => IPIP.len(),
542 SitTun => SIT.len(),
543 GreTun => GRE.len(),
544 GreTun6 => IP6GRE.len(),
545 Vti => VTI.len(),
546 Vrf => VRF.len(),
547 Gtp => GTP.len(),
548 Ipoib => IPOIB.len(),
549 Wireguard => WIREGUARD.len(),
550 Xfrm => XFRM.len(),
551 MacSec => MACSEC.len(),
552 Other(ref s) => s.len(),
553 };
554 len + 1
555 }
556
557 fn emit_value(&self, buffer: &mut [u8]) {
558 use self::InfoKind::*;
559 let s = match *self {
560 Dummy => DUMMY,
561 Ifb => IFB,
562 Bridge => BRIDGE,
563 Tun => TUN,
564 Nlmon => NLMON,
565 Vlan => VLAN,
566 Veth => VETH,
567 Vxlan => VXLAN,
568 Bond => BOND,
569 IpVlan => IPVLAN,
570 MacVlan => MACVLAN,
571 MacVtap => MACVTAP,
572 GreTap => GRETAP,
573 GreTap6 => IP6GRETAP,
574 IpTun => IPIP,
575 SitTun => SIT,
576 GreTun => GRE,
577 GreTun6 => IP6GRE,
578 Vti => VTI,
579 Vrf => VRF,
580 Gtp => GTP,
581 Ipoib => IPOIB,
582 Wireguard => WIREGUARD,
583 Xfrm => XFRM,
584 MacSec => MACSEC,
585 Other(ref s) => s.as_str(),
586 };
587 buffer[..s.len()].copy_from_slice(s.as_bytes());
588 buffer[s.len()] = 0;
589 }
590
591 fn kind(&self) -> u16 {
592 IFLA_INFO_KIND
593 }
594}
595
596impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoKind {
597 fn parse(buf: &NlaBuffer<&'a T>) -> Result<InfoKind, DecodeError> {
598 use self::InfoKind::*;
599 if buf.kind() != IFLA_INFO_KIND {
600 return Err(format!(
601 "failed to parse IFLA_INFO_KIND: NLA type is {}",
602 buf.kind()
603 )
604 .into());
605 }
606 let s = parse_string(buf.value())
607 .context("invalid IFLA_INFO_KIND value")?;
608 Ok(match s.as_str() {
609 DUMMY => Dummy,
610 IFB => Ifb,
611 BRIDGE => Bridge,
612 TUN => Tun,
613 NLMON => Nlmon,
614 VLAN => Vlan,
615 VETH => Veth,
616 VXLAN => Vxlan,
617 BOND => Bond,
618 IPVLAN => IpVlan,
619 MACVLAN => MacVlan,
620 MACVTAP => MacVtap,
621 GRETAP => GreTap,
622 IP6GRETAP => GreTap6,
623 IPIP => IpTun,
624 SIT => SitTun,
625 GRE => GreTun,
626 IP6GRE => GreTun6,
627 VTI => Vti,
628 VRF => Vrf,
629 GTP => Gtp,
630 IPOIB => Ipoib,
631 WIREGUARD => Wireguard,
632 MACSEC => MacSec,
633 _ => Other(s),
634 })
635 }
636}
637
638#[derive(Debug, PartialEq, Eq, Clone)]
639#[non_exhaustive]
640pub enum InfoPortKind {
641 Bond,
642 Other(String),
643}
644
645impl Nla for InfoPortKind {
646 fn value_len(&self) -> usize {
647 use self::InfoPortKind::*;
648 let len = match *self {
649 Bond => BOND.len(),
650 Other(ref s) => s.len(),
651 };
652 len + 1
653 }
654
655 fn emit_value(&self, buffer: &mut [u8]) {
656 use self::InfoPortKind::*;
657 let s = match *self {
658 Bond => BOND,
659 Other(ref s) => s.as_str(),
660 };
661 buffer[..s.len()].copy_from_slice(s.as_bytes());
662 buffer[s.len()] = 0;
663 }
664
665 fn kind(&self) -> u16 {
666 IFLA_INFO_PORT_KIND
667 }
668}
669
670impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoPortKind {
671 fn parse(buf: &NlaBuffer<&'a T>) -> Result<InfoPortKind, DecodeError> {
672 use self::InfoPortKind::*;
673 if buf.kind() != IFLA_INFO_PORT_KIND {
674 return Err(format!(
675 "failed to parse IFLA_INFO_PORT_KIND: NLA type is {}",
676 buf.kind()
677 )
678 .into());
679 }
680 let s = parse_string(buf.value())
681 .context("invalid IFLA_INFO_PORT_KIND value")?;
682 Ok(match s.as_str() {
683 BOND => Bond,
684 _ => Other(s),
685 })
686 }
687}
688
689#[derive(Debug, PartialEq, Eq, Clone)]
691#[non_exhaustive]
692pub enum InfoVxlan {
693 Unspec(Vec<u8>),
694 Id(u32),
695 Group(Vec<u8>),
696 Group6(Vec<u8>),
697 Link(u32),
698 Local(Vec<u8>),
699 Local6(Vec<u8>),
700 Tos(u8),
701 Ttl(u8),
702 Label(u32),
703 Learning(u8),
704 Ageing(u32),
705 Limit(u32),
706 PortRange((u16, u16)),
707 Proxy(u8),
708 Rsc(u8),
709 L2Miss(u8),
710 L3Miss(u8),
711 CollectMetadata(u8),
712 Port(u16),
713 UDPCsum(u8),
714 UDPZeroCsumTX(u8),
715 UDPZeroCsumRX(u8),
716 RemCsumTX(u8),
717 RemCsumRX(u8),
718 Gbp(u8),
719 Gpe(u8),
720 RemCsumNoPartial(u8),
721 TtlInherit(u8),
722 Df(u8),
723}
724
725impl Nla for InfoVxlan {
726 #[rustfmt::skip]
727 fn value_len(&self) -> usize {
728 use self::InfoVxlan::*;
729 match *self {
730 Tos(_)
731 | Ttl(_)
732 | Learning(_)
733 | Proxy(_)
734 | Rsc(_)
735 | L2Miss(_)
736 | L3Miss(_)
737 | CollectMetadata(_)
738 | UDPCsum(_)
739 | UDPZeroCsumTX(_)
740 | UDPZeroCsumRX(_)
741 | RemCsumTX(_)
742 | RemCsumRX(_)
743 | Gbp(_)
744 | Gpe(_)
745 | RemCsumNoPartial(_)
746 | TtlInherit(_)
747 | Df(_)
748 => 1,
749 Port(_) => 2,
750 Id(_)
751 | Label(_)
752 | Link(_)
753 | Ageing(_)
754 | Limit(_)
755 | PortRange(_)
756 => 4,
757 Local(ref bytes)
758 | Local6(ref bytes)
759 | Group(ref bytes)
760 | Group6(ref bytes)
761 | Unspec(ref bytes)
762 => bytes.len(),
763 }
764 }
765
766 #[rustfmt::skip]
767 fn emit_value(&self, buffer: &mut [u8]) {
768 use self::InfoVxlan::*;
769 match self {
770 Unspec(ref bytes) => buffer.copy_from_slice(bytes),
771 Id(ref value)
772 | Label(ref value)
773 | Link(ref value)
774 | Ageing(ref value)
775 | Limit(ref value)
776 => NativeEndian::write_u32(buffer, *value),
777 Tos(ref value)
778 | Ttl(ref value)
779 | Learning (ref value)
780 | Proxy(ref value)
781 | Rsc(ref value)
782 | L2Miss(ref value)
783 | L3Miss(ref value)
784 | CollectMetadata(ref value)
785 | UDPCsum(ref value)
786 | UDPZeroCsumTX(ref value)
787 | UDPZeroCsumRX(ref value)
788 | RemCsumTX(ref value)
789 | RemCsumRX(ref value)
790 | Gbp(ref value)
791 | Gpe(ref value)
792 | RemCsumNoPartial(ref value)
793 | TtlInherit(ref value)
794 | Df(ref value)
795 => buffer[0] = *value,
796 Local(ref value)
797 | Group(ref value)
798 | Group6(ref value)
799 | Local6(ref value)
800 => buffer.copy_from_slice(value.as_slice()),
801 Port(ref value) => BigEndian::write_u16(buffer, *value),
802 PortRange(ref range) => {
803 BigEndian::write_u16(buffer, range.0);
804 BigEndian::write_u16(&mut buffer[2..], range.1)
805 }
806 }
807 }
808
809 fn kind(&self) -> u16 {
810 use self::InfoVxlan::*;
811
812 match self {
813 Id(_) => IFLA_VXLAN_ID,
814 Group(_) => IFLA_VXLAN_GROUP,
815 Group6(_) => IFLA_VXLAN_GROUP6,
816 Link(_) => IFLA_VXLAN_LINK,
817 Local(_) => IFLA_VXLAN_LOCAL,
818 Local6(_) => IFLA_VXLAN_LOCAL6,
819 Tos(_) => IFLA_VXLAN_TOS,
820 Ttl(_) => IFLA_VXLAN_TTL,
821 Label(_) => IFLA_VXLAN_LABEL,
822 Learning(_) => IFLA_VXLAN_LEARNING,
823 Ageing(_) => IFLA_VXLAN_AGEING,
824 Limit(_) => IFLA_VXLAN_LIMIT,
825 PortRange(_) => IFLA_VXLAN_PORT_RANGE,
826 Proxy(_) => IFLA_VXLAN_PROXY,
827 Rsc(_) => IFLA_VXLAN_RSC,
828 L2Miss(_) => IFLA_VXLAN_L2MISS,
829 L3Miss(_) => IFLA_VXLAN_L3MISS,
830 CollectMetadata(_) => IFLA_VXLAN_COLLECT_METADATA,
831 Port(_) => IFLA_VXLAN_PORT,
832 UDPCsum(_) => IFLA_VXLAN_UDP_CSUM,
833 UDPZeroCsumTX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
834 UDPZeroCsumRX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
835 RemCsumTX(_) => IFLA_VXLAN_REMCSUM_TX,
836 RemCsumRX(_) => IFLA_VXLAN_REMCSUM_RX,
837 Gbp(_) => IFLA_VXLAN_GBP,
838 Gpe(_) => IFLA_VXLAN_GPE,
839 RemCsumNoPartial(_) => IFLA_VXLAN_REMCSUM_NOPARTIAL,
840 TtlInherit(_) => IFLA_VXLAN_TTL_INHERIT,
841 Df(_) => IFLA_VXLAN_DF,
842 Unspec(_) => IFLA_VXLAN_UNSPEC,
843 }
844 }
845}
846
847impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVxlan {
848 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
849 use self::InfoVxlan::*;
850 let payload = buf.value();
851 Ok(match buf.kind() {
852 IFLA_VLAN_UNSPEC => Unspec(payload.to_vec()),
853 IFLA_VXLAN_ID => {
854 Id(parse_u32(payload).context("invalid IFLA_VXLAN_ID value")?)
855 }
856 IFLA_VXLAN_GROUP => Group(payload.to_vec()),
857 IFLA_VXLAN_GROUP6 => Group6(payload.to_vec()),
858 IFLA_VXLAN_LINK => Link(
859 parse_u32(payload).context("invalid IFLA_VXLAN_LINK value")?,
860 ),
861 IFLA_VXLAN_LOCAL => Local(payload.to_vec()),
862 IFLA_VXLAN_LOCAL6 => Local6(payload.to_vec()),
863 IFLA_VXLAN_TOS => {
864 Tos(parse_u8(payload)
865 .context("invalid IFLA_VXLAN_TOS value")?)
866 }
867 IFLA_VXLAN_TTL => {
868 Ttl(parse_u8(payload)
869 .context("invalid IFLA_VXLAN_TTL value")?)
870 }
871 IFLA_VXLAN_LABEL => Label(
872 parse_u32(payload).context("invalid IFLA_VXLAN_LABEL value")?,
873 ),
874 IFLA_VXLAN_LEARNING => Learning(
875 parse_u8(payload)
876 .context("invalid IFLA_VXLAN_LEARNING value")?,
877 ),
878 IFLA_VXLAN_AGEING => Ageing(
879 parse_u32(payload)
880 .context("invalid IFLA_VXLAN_AGEING value")?,
881 ),
882 IFLA_VXLAN_LIMIT => Limit(
883 parse_u32(payload).context("invalid IFLA_VXLAN_LIMIT value")?,
884 ),
885 IFLA_VXLAN_PROXY => Proxy(
886 parse_u8(payload).context("invalid IFLA_VXLAN_PROXY value")?,
887 ),
888 IFLA_VXLAN_RSC => {
889 Rsc(parse_u8(payload)
890 .context("invalid IFLA_VXLAN_RSC value")?)
891 }
892 IFLA_VXLAN_L2MISS => L2Miss(
893 parse_u8(payload).context("invalid IFLA_VXLAN_L2MISS value")?,
894 ),
895 IFLA_VXLAN_L3MISS => L3Miss(
896 parse_u8(payload).context("invalid IFLA_VXLAN_L3MISS value")?,
897 ),
898 IFLA_VXLAN_COLLECT_METADATA => CollectMetadata(
899 parse_u8(payload)
900 .context("invalid IFLA_VXLAN_COLLECT_METADATA value")?,
901 ),
902 IFLA_VXLAN_PORT_RANGE => {
903 let err = "invalid IFLA_VXLAN_PORT value";
904 if payload.len() != 4 {
905 return Err(err.into());
906 }
907 let low = parse_u16_be(&payload[0..2]).context(err)?;
908 let high = parse_u16_be(&payload[2..]).context(err)?;
909 PortRange((low, high))
910 }
911 IFLA_VXLAN_PORT => Port(
912 parse_u16_be(payload)
913 .context("invalid IFLA_VXLAN_PORT value")?,
914 ),
915 IFLA_VXLAN_UDP_CSUM => UDPCsum(
916 parse_u8(payload)
917 .context("invalid IFLA_VXLAN_UDP_CSUM value")?,
918 ),
919 IFLA_VXLAN_UDP_ZERO_CSUM6_TX => UDPZeroCsumTX(
920 parse_u8(payload)
921 .context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_TX value")?,
922 ),
923 IFLA_VXLAN_UDP_ZERO_CSUM6_RX => UDPZeroCsumRX(
924 parse_u8(payload)
925 .context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_RX value")?,
926 ),
927 IFLA_VXLAN_REMCSUM_TX => RemCsumTX(
928 parse_u8(payload)
929 .context("invalid IFLA_VXLAN_REMCSUM_TX value")?,
930 ),
931 IFLA_VXLAN_REMCSUM_RX => RemCsumRX(
932 parse_u8(payload)
933 .context("invalid IFLA_VXLAN_REMCSUM_RX value")?,
934 ),
935 IFLA_VXLAN_DF => {
936 Df(parse_u8(payload).context("invalid IFLA_VXLAN_DF value")?)
937 }
938 IFLA_VXLAN_GBP => {
939 Gbp(parse_u8(payload)
940 .context("invalid IFLA_VXLAN_GBP value")?)
941 }
942 IFLA_VXLAN_GPE => {
943 Gpe(parse_u8(payload)
944 .context("invalid IFLA_VXLAN_GPE value")?)
945 }
946 IFLA_VXLAN_REMCSUM_NOPARTIAL => RemCsumNoPartial(
947 parse_u8(payload)
948 .context("invalid IFLA_VXLAN_REMCSUM_NO_PARTIAL")?,
949 ),
950 IFLA_VXLAN_TTL_INHERIT => TtlInherit(
951 parse_u8(payload)
952 .context("invalid IFLA_VXLAN_TTL_INHERIT value")?,
953 ),
954 __IFLA_VXLAN_MAX => Unspec(payload.to_vec()),
955 _ => return Err(format!("unknown NLA type {}", buf.kind()).into()),
956 })
957 }
958}
959
960#[derive(Debug, PartialEq, Eq, Clone)]
962#[non_exhaustive]
963pub enum InfoVlan {
964 Unspec(Vec<u8>),
965 Id(u16),
966 Flags((u32, u32)),
967 EgressQos(Vec<VlanQosMapping>),
968 IngressQos(Vec<VlanQosMapping>),
969 Protocol(u16),
970}
971
972impl Nla for InfoVlan {
973 #[rustfmt::skip]
974 fn value_len(&self) -> usize {
975 use self::InfoVlan::*;
976 match self {
977 Id(_) | Protocol(_) => 2,
978 Flags(_) => 8,
979 Unspec(bytes) => bytes.len(),
980 EgressQos(mappings)
981 | IngressQos(mappings)
982 => mappings.as_slice().buffer_len(),
983 }
984 }
985
986 #[rustfmt::skip]
987 fn emit_value(&self, buffer: &mut [u8]) {
988 use self::InfoVlan::*;
989 match self {
990 Unspec(ref bytes)
991 => buffer.copy_from_slice(bytes),
992 EgressQos(ref mappings)
993 | IngressQos(ref mappings) => mappings.as_slice().emit(buffer),
994 Id(ref value)
995 | Protocol(ref value)
996 => NativeEndian::write_u16(buffer, *value),
997
998 Flags(ref flags) => {
999 NativeEndian::write_u32(buffer, flags.0);
1000 NativeEndian::write_u32(buffer, flags.1)
1001 }
1002 }
1003 }
1004
1005 fn kind(&self) -> u16 {
1006 use self::InfoVlan::*;
1007 match self {
1008 Unspec(_) => IFLA_VLAN_UNSPEC,
1009 Id(_) => IFLA_VLAN_ID,
1010 Flags(_) => IFLA_VLAN_FLAGS,
1011 EgressQos(_) => IFLA_VLAN_EGRESS_QOS,
1012 IngressQos(_) => IFLA_VLAN_INGRESS_QOS,
1013 Protocol(_) => IFLA_VLAN_PROTOCOL,
1014 }
1015 }
1016}
1017
1018fn parse_mappings(payload: &[u8]) -> Result<Vec<VlanQosMapping>, DecodeError> {
1019 let mut mappings = Vec::new();
1020 for nla in NlasIterator::new(payload) {
1021 let nla = nla?;
1022 let parsed = VlanQosMapping::parse(&nla)?;
1023 mappings.push(parsed);
1024 }
1025 Ok(mappings)
1026}
1027
1028impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVlan {
1029 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1030 use self::InfoVlan::*;
1031 let payload = buf.value();
1032 Ok(match buf.kind() {
1033 IFLA_VLAN_UNSPEC => Unspec(payload.to_vec()),
1034 IFLA_VLAN_ID => {
1035 Id(parse_u16(payload).context("invalid IFLA_VLAN_ID value")?)
1036 }
1037 IFLA_VLAN_FLAGS => {
1038 let err = "invalid IFLA_VLAN_FLAGS value";
1039 if payload.len() != 8 {
1040 return Err(err.into());
1041 }
1042 let flags = parse_u32(&payload[0..4]).context(err)?;
1043 let mask = parse_u32(&payload[4..]).context(err)?;
1044 Flags((flags, mask))
1045 }
1046 IFLA_VLAN_EGRESS_QOS => EgressQos(
1047 parse_mappings(payload)
1048 .context("failed to parse IFLA_VLAN_EGRESS_QOS")?,
1049 ),
1050 IFLA_VLAN_INGRESS_QOS => IngressQos(
1051 parse_mappings(payload)
1052 .context("failed to parse IFLA_VLAN_INGRESS_QOS")?,
1053 ),
1054 IFLA_VLAN_PROTOCOL => Protocol(
1055 parse_u16_be(payload)
1056 .context("invalid IFLA_VLAN_PROTOCOL value")?,
1057 ),
1058 _ => return Err(format!("unknown NLA type {}", buf.kind()).into()),
1059 })
1060 }
1061}
1062
1063#[derive(Debug, PartialEq, Eq, Clone)]
1064#[non_exhaustive]
1065pub enum InfoIpoib {
1066 Unspec(Vec<u8>),
1067 Pkey(u16),
1068 Mode(u16),
1069 UmCast(u16),
1070 Other(DefaultNla),
1071}
1072
1073impl Nla for InfoIpoib {
1074 fn value_len(&self) -> usize {
1075 use self::InfoIpoib::*;
1076 match self {
1077 Unspec(bytes) => bytes.len(),
1078 Pkey(_) | Mode(_) | UmCast(_) => 2,
1079 Other(nla) => nla.value_len(),
1080 }
1081 }
1082
1083 fn emit_value(&self, buffer: &mut [u8]) {
1084 use self::InfoIpoib::*;
1085 match self {
1086 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1087 Pkey(value) => NativeEndian::write_u16(buffer, *value),
1088 Mode(value) => NativeEndian::write_u16(buffer, *value),
1089 UmCast(value) => NativeEndian::write_u16(buffer, *value),
1090 Other(nla) => nla.emit_value(buffer),
1091 }
1092 }
1093
1094 fn kind(&self) -> u16 {
1095 use self::InfoIpoib::*;
1096 match self {
1097 Unspec(_) => IFLA_IPOIB_UNSPEC,
1098 Pkey(_) => IFLA_IPOIB_PKEY,
1099 Mode(_) => IFLA_IPOIB_MODE,
1100 UmCast(_) => IFLA_IPOIB_UMCAST,
1101 Other(nla) => nla.kind(),
1102 }
1103 }
1104}
1105
1106impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpoib {
1107 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1108 use self::InfoIpoib::*;
1109 let payload = buf.value();
1110 Ok(match buf.kind() {
1111 IFLA_IPOIB_UNSPEC => Unspec(payload.to_vec()),
1112 IFLA_IPOIB_PKEY => Pkey(
1113 parse_u16(payload).context("invalid IFLA_IPOIB_PKEY value")?,
1114 ),
1115 IFLA_IPOIB_MODE => Mode(
1116 parse_u16(payload).context("invalid IFLA_IPOIB_MODE value")?,
1117 ),
1118 IFLA_IPOIB_UMCAST => UmCast(
1119 parse_u16(payload)
1120 .context("invalid IFLA_IPOIB_UMCAST value")?,
1121 ),
1122 kind => Other(
1123 DefaultNla::parse(buf)
1124 .context(format!("unknown NLA type {kind}"))?,
1125 ),
1126 })
1127 }
1128}
1129
1130#[derive(Debug, PartialEq, Eq, Clone)]
1131#[non_exhaustive]
1132pub enum VethInfo {
1133 Unspec(Vec<u8>),
1134 Peer(LinkMessage),
1135 Other(DefaultNla),
1136}
1137
1138impl Nla for VethInfo {
1139 fn value_len(&self) -> usize {
1140 use self::VethInfo::*;
1141 match *self {
1142 Unspec(ref bytes) => bytes.len(),
1143 Peer(ref message) => message.buffer_len(),
1144 Other(ref attr) => attr.value_len(),
1145 }
1146 }
1147
1148 fn emit_value(&self, buffer: &mut [u8]) {
1149 use self::VethInfo::*;
1150 match *self {
1151 Unspec(ref bytes) => buffer.copy_from_slice(bytes.as_slice()),
1152 Peer(ref message) => message.emit(buffer),
1153 Other(ref attr) => attr.emit_value(buffer),
1154 }
1155 }
1156
1157 fn kind(&self) -> u16 {
1158 use self::VethInfo::*;
1159 match *self {
1160 Unspec(_) => VETH_INFO_UNSPEC,
1161 Peer(_) => VETH_INFO_PEER,
1162 Other(ref attr) => attr.kind(),
1163 }
1164 }
1165}
1166
1167impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VethInfo {
1168 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1169 use self::VethInfo::*;
1170 let payload = buf.value();
1171 Ok(match buf.kind() {
1172 VETH_INFO_UNSPEC => Unspec(payload.to_vec()),
1173 VETH_INFO_PEER => {
1174 let err = "failed to parse veth link info";
1175 let buffer =
1176 LinkMessageBuffer::new_checked(&payload).context(err)?;
1177 Peer(LinkMessage::parse(&buffer).context(err)?)
1178 }
1179 kind => Other(
1180 DefaultNla::parse(buf)
1181 .context(format!("unknown NLA type {kind}"))?,
1182 ),
1183 })
1184 }
1185}
1186
1187#[derive(Debug, PartialEq, Eq, Clone)]
1188#[non_exhaustive]
1189pub enum InfoIpVlan {
1190 Unspec(Vec<u8>),
1191 Mode(u16),
1192 Flags(u16),
1193 Other(DefaultNla),
1194}
1195
1196impl Nla for InfoIpVlan {
1197 fn value_len(&self) -> usize {
1198 use self::InfoIpVlan::*;
1199 match self {
1200 Unspec(bytes) => bytes.len(),
1201 Mode(_) | Flags(_) => 2,
1202 Other(nla) => nla.value_len(),
1203 }
1204 }
1205
1206 fn emit_value(&self, buffer: &mut [u8]) {
1207 use self::InfoIpVlan::*;
1208 match self {
1209 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1210 Mode(value) => NativeEndian::write_u16(buffer, *value),
1211 Flags(value) => NativeEndian::write_u16(buffer, *value),
1212 Other(nla) => nla.emit_value(buffer),
1213 }
1214 }
1215
1216 fn kind(&self) -> u16 {
1217 use self::InfoIpVlan::*;
1218 match self {
1219 Unspec(_) => IFLA_IPVLAN_UNSPEC,
1220 Mode(_) => IFLA_IPVLAN_MODE,
1221 Flags(_) => IFLA_IPVLAN_FLAGS,
1222 Other(nla) => nla.kind(),
1223 }
1224 }
1225}
1226
1227impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVlan {
1228 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1229 use self::InfoIpVlan::*;
1230 let payload = buf.value();
1231 Ok(match buf.kind() {
1232 IFLA_IPVLAN_UNSPEC => Unspec(payload.to_vec()),
1233 IFLA_IPVLAN_MODE => Mode(
1234 parse_u16(payload).context("invalid IFLA_IPVLAN_MODE value")?,
1235 ),
1236 IFLA_IPVLAN_FLAGS => Flags(
1237 parse_u16(payload)
1238 .context("invalid IFLA_IPVLAN_FLAGS value")?,
1239 ),
1240 kind => Other(
1241 DefaultNla::parse(buf)
1242 .context(format!("unknown NLA type {kind}"))?,
1243 ),
1244 })
1245 }
1246}
1247
1248#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1249#[non_exhaustive]
1250pub enum MacSecCipherId {
1251 #[deprecated]
1252 DefaultGcmAes128,
1253 GcmAes128,
1254 GcmAes256,
1255 GcmAesXpn128,
1256 GcmAesXpn256,
1257 Other(u64),
1258}
1259
1260impl From<u64> for MacSecCipherId {
1261 fn from(d: u64) -> Self {
1262 match d {
1263 #[allow(deprecated)]
1264 MACSEC_DEFAULT_CIPHER_ID => Self::DefaultGcmAes128,
1265 MACSEC_CIPHER_ID_GCM_AES_128 => Self::GcmAes128,
1266 MACSEC_CIPHER_ID_GCM_AES_256 => Self::GcmAes256,
1267 MACSEC_CIPHER_ID_GCM_AES_XPN_128 => Self::GcmAesXpn128,
1268 MACSEC_CIPHER_ID_GCM_AES_XPN_256 => Self::GcmAesXpn256,
1269 _ => Self::Other(d),
1270 }
1271 }
1272}
1273
1274impl From<MacSecCipherId> for u64 {
1275 fn from(d: MacSecCipherId) -> Self {
1276 match d {
1277 #[allow(deprecated)]
1278 MacSecCipherId::DefaultGcmAes128 => MACSEC_DEFAULT_CIPHER_ID,
1279 MacSecCipherId::GcmAes128 => MACSEC_CIPHER_ID_GCM_AES_128,
1280 MacSecCipherId::GcmAes256 => MACSEC_CIPHER_ID_GCM_AES_256,
1281 MacSecCipherId::GcmAesXpn128 => MACSEC_CIPHER_ID_GCM_AES_XPN_128,
1282 MacSecCipherId::GcmAesXpn256 => MACSEC_CIPHER_ID_GCM_AES_XPN_256,
1283 MacSecCipherId::Other(value) => value,
1284 }
1285 }
1286}
1287
1288#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1289#[non_exhaustive]
1290pub enum MacSecValidation {
1291 Disabled,
1292 Check,
1293 Strict,
1294 Other(u8),
1295}
1296
1297impl From<u8> for MacSecValidation {
1298 fn from(d: u8) -> Self {
1299 match d {
1300 MACSEC_VALIDATE_DISABLED => Self::Disabled,
1301 MACSEC_VALIDATE_CHECK => Self::Check,
1302 MACSEC_VALIDATE_STRICT => Self::Strict,
1303 _ => Self::Other(d),
1304 }
1305 }
1306}
1307
1308impl From<MacSecValidation> for u8 {
1309 fn from(d: MacSecValidation) -> Self {
1310 match d {
1311 MacSecValidation::Disabled => MACSEC_VALIDATE_DISABLED,
1312 MacSecValidation::Check => MACSEC_VALIDATE_CHECK,
1313 MacSecValidation::Strict => MACSEC_VALIDATE_STRICT,
1314 MacSecValidation::Other(value) => value,
1315 }
1316 }
1317}
1318
1319#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1320#[non_exhaustive]
1321pub enum MacSecOffload {
1322 Off,
1323 Phy,
1324 Mac,
1325 Other(u8),
1326}
1327
1328impl From<u8> for MacSecOffload {
1329 fn from(d: u8) -> Self {
1330 match d {
1331 MACSEC_OFFLOAD_OFF => Self::Off,
1332 MACSEC_OFFLOAD_PHY => Self::Phy,
1333 MACSEC_OFFLOAD_MAC => Self::Mac,
1334 _ => Self::Other(d),
1335 }
1336 }
1337}
1338
1339impl From<MacSecOffload> for u8 {
1340 fn from(d: MacSecOffload) -> Self {
1341 match d {
1342 MacSecOffload::Off => MACSEC_OFFLOAD_OFF,
1343 MacSecOffload::Phy => MACSEC_OFFLOAD_PHY,
1344 MacSecOffload::Mac => MACSEC_OFFLOAD_MAC,
1345 MacSecOffload::Other(value) => value,
1346 }
1347 }
1348}
1349
1350#[derive(Debug, PartialEq, Eq, Clone)]
1351#[non_exhaustive]
1352pub enum InfoMacSec {
1353 Unspec(Vec<u8>),
1354 Sci(u64),
1355 Port(u16),
1356 IcvLen(u8),
1357 CipherSuite(MacSecCipherId),
1358 Window(u32),
1359 EncodingSa(u8),
1360 Encrypt(u8),
1361 Protect(u8),
1362 IncSci(u8),
1363 Es(u8),
1364 Scb(u8),
1365 ReplayProtect(u8),
1366 Validation(MacSecValidation),
1367 Offload(MacSecOffload),
1368 Other(DefaultNla),
1369}
1370
1371impl Nla for InfoMacSec {
1372 fn value_len(&self) -> usize {
1373 use self::InfoMacSec::*;
1374 match self {
1375 Unspec(bytes) => bytes.len(),
1376 Sci(_) | CipherSuite(_) => 8,
1377 Window(_) => 4,
1378 Port(_) => 2,
1379 IcvLen(_) | EncodingSa(_) | Encrypt(_) | Protect(_) | IncSci(_)
1380 | Es(_) | Scb(_) | ReplayProtect(_) | Validation(_)
1381 | Offload(_) => 1,
1382 Other(nla) => nla.value_len(),
1383 }
1384 }
1385
1386 fn emit_value(&self, buffer: &mut [u8]) {
1387 use self::InfoMacSec::*;
1388 match self {
1389 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1390 Sci(value) => NativeEndian::write_u64(buffer, *value),
1391 CipherSuite(value) => {
1392 NativeEndian::write_u64(buffer, (*value).into())
1393 }
1394 Window(value) => NativeEndian::write_u32(buffer, *value),
1395 Port(value) => NativeEndian::write_u16(buffer, *value),
1396 IcvLen(value) | EncodingSa(value) | Encrypt(value)
1397 | Protect(value) | IncSci(value) | Es(value) | Scb(value)
1398 | ReplayProtect(value) => buffer[0] = *value,
1399 Offload(value) => buffer[0] = (*value).into(),
1400 Validation(value) => buffer[0] = (*value).into(),
1401 Other(nla) => nla.emit_value(buffer),
1402 }
1403 }
1404
1405 fn kind(&self) -> u16 {
1406 use self::InfoMacSec::*;
1407 match self {
1408 Unspec(_) => IFLA_MACSEC_UNSPEC,
1409 Sci(_) => IFLA_MACSEC_SCI,
1410 Port(_) => IFLA_MACSEC_PORT,
1411 IcvLen(_) => IFLA_MACSEC_ICV_LEN,
1412 CipherSuite(_) => IFLA_MACSEC_CIPHER_SUITE,
1413 Window(_) => IFLA_MACSEC_WINDOW,
1414 EncodingSa(_) => IFLA_MACSEC_ENCODING_SA,
1415 Encrypt(_) => IFLA_MACSEC_ENCRYPT,
1416 Protect(_) => IFLA_MACSEC_PROTECT,
1417 IncSci(_) => IFLA_MACSEC_INC_SCI,
1418 Es(_) => IFLA_MACSEC_ES,
1419 Scb(_) => IFLA_MACSEC_SCB,
1420 ReplayProtect(_) => IFLA_MACSEC_REPLAY_PROTECT,
1421 Validation(_) => IFLA_MACSEC_VALIDATION,
1422 Offload(_) => IFLA_MACSEC_OFFLOAD,
1423 Other(nla) => nla.kind(),
1424 }
1425 }
1426}
1427
1428impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacSec {
1429 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1430 use self::InfoMacSec::*;
1431 let payload = buf.value();
1432 Ok(match buf.kind() {
1433 IFLA_MACSEC_UNSPEC => Unspec(payload.to_vec()),
1434 IFLA_MACSEC_SCI => {
1435 Sci(parse_u64(payload)
1436 .context("invalid IFLA_MACSEC_SCI value")?)
1437 }
1438 IFLA_MACSEC_PORT => Port(
1439 parse_u16(payload).context("invalid IFLA_MACSEC_PORT value")?,
1440 ),
1441 IFLA_MACSEC_ICV_LEN => IcvLen(
1442 parse_u8(payload)
1443 .context("invalid IFLA_MACSEC_ICV_LEN value")?,
1444 ),
1445 IFLA_MACSEC_CIPHER_SUITE => CipherSuite(
1446 parse_u64(payload)
1447 .context("invalid IFLA_MACSEC_CIPHER_SUITE value")?
1448 .into(),
1449 ),
1450 IFLA_MACSEC_WINDOW => Window(
1451 parse_u32(payload)
1452 .context("invalid IFLA_MACSEC_WINDOW value")?,
1453 ),
1454 IFLA_MACSEC_ENCODING_SA => EncodingSa(
1455 parse_u8(payload)
1456 .context("invalid IFLA_MACSEC_ENCODING_SA value")?,
1457 ),
1458 IFLA_MACSEC_ENCRYPT => Encrypt(
1459 parse_u8(payload)
1460 .context("invalid IFLA_MACSEC_ENCRYPT value")?,
1461 ),
1462 IFLA_MACSEC_PROTECT => Protect(
1463 parse_u8(payload)
1464 .context("invalid IFLA_MACSEC_PROTECT value")?,
1465 ),
1466 IFLA_MACSEC_INC_SCI => IncSci(
1467 parse_u8(payload)
1468 .context("invalid IFLA_MACSEC_INC_SCI value")?,
1469 ),
1470 IFLA_MACSEC_ES => {
1471 Es(parse_u8(payload).context("invalid IFLA_MACSEC_ES value")?)
1472 }
1473 IFLA_MACSEC_SCB => {
1474 Scb(parse_u8(payload)
1475 .context("invalid IFLA_MACSEC_SCB value")?)
1476 }
1477 IFLA_MACSEC_REPLAY_PROTECT => ReplayProtect(
1478 parse_u8(payload)
1479 .context("invalid IFLA_MACSEC_REPLAY_PROTECT value")?,
1480 ),
1481 IFLA_MACSEC_VALIDATION => Validation(
1482 parse_u8(payload)
1483 .context("invalid IFLA_MACSEC_VALIDATION value")?
1484 .into(),
1485 ),
1486 IFLA_MACSEC_OFFLOAD => Offload(
1487 parse_u8(payload)
1488 .context("invalid IFLA_MACSEC_OFFLOAD value")?
1489 .into(),
1490 ),
1491 kind => Other(
1492 DefaultNla::parse(buf)
1493 .context(format!("unknown NLA type {kind}"))?,
1494 ),
1495 })
1496 }
1497}
1498
1499#[derive(Debug, PartialEq, Eq, Clone)]
1500#[non_exhaustive]
1501pub enum InfoXfrmTun {
1502 Unspec(Vec<u8>),
1503 Link(u32),
1504 IfId(u32),
1505 Other(DefaultNla),
1506}
1507
1508impl Nla for InfoXfrmTun {
1509 fn value_len(&self) -> usize {
1510 use self::InfoXfrmTun::*;
1511 match self {
1512 Unspec(bytes) => bytes.len(),
1513 Link(_) => 4,
1514 IfId(_) => 4,
1515 Other(nla) => nla.value_len(),
1516 }
1517 }
1518
1519 fn emit_value(&self, buffer: &mut [u8]) {
1520 use self::InfoXfrmTun::*;
1521 match self {
1522 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1523 Link(value) => NativeEndian::write_u32(buffer, *value),
1524 IfId(value) => NativeEndian::write_u32(buffer, *value),
1525 Other(nla) => nla.emit_value(buffer),
1526 }
1527 }
1528
1529 fn kind(&self) -> u16 {
1530 use self::InfoXfrmTun::*;
1531 match self {
1532 Unspec(_) => IFLA_XFRM_UNSPEC,
1533 Link(_) => IFLA_XFRM_LINK,
1534 IfId(_) => IFLA_XFRM_IF_ID,
1535 Other(nla) => nla.kind(),
1536 }
1537 }
1538}
1539
1540impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoXfrmTun {
1541 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1542 use self::InfoXfrmTun::*;
1543 let payload = buf.value();
1544 Ok(match buf.kind() {
1545 IFLA_XFRM_UNSPEC => Unspec(payload.to_vec()),
1546 IFLA_XFRM_LINK => Link(
1547 parse_u32(payload).context("invalid IFLA_XFRM_IF_ID value")?,
1548 ),
1549 IFLA_XFRM_IF_ID => IfId(
1550 parse_u32(payload).context("invalid IFLA_XFRM_IF_ID value")?,
1551 ),
1552 kind => Other(
1553 DefaultNla::parse(buf)
1554 .context(format!("unknown NLA type {kind}"))?,
1555 ),
1556 })
1557 }
1558}
1559
1560#[derive(Debug, PartialEq, Eq, Clone)]
1561#[non_exhaustive]
1562pub enum InfoVrf {
1563 TableId(u32),
1564 Other(DefaultNla),
1565}
1566
1567impl Nla for InfoVrf {
1568 fn value_len(&self) -> usize {
1569 use self::InfoVrf::*;
1570 match self {
1571 TableId(_) => 4,
1572 Other(nla) => nla.value_len(),
1573 }
1574 }
1575
1576 fn emit_value(&self, buffer: &mut [u8]) {
1577 use self::InfoVrf::*;
1578 match self {
1579 TableId(value) => NativeEndian::write_u32(buffer, *value),
1580 Other(nla) => nla.emit_value(buffer),
1581 }
1582 }
1583
1584 fn kind(&self) -> u16 {
1585 use self::InfoVrf::*;
1586 match self {
1587 TableId(_) => IFLA_VRF_TABLE,
1588 Other(nla) => nla.kind(),
1589 }
1590 }
1591}
1592
1593impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVrf {
1594 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1595 use self::InfoVrf::*;
1596 let payload = buf.value();
1597 Ok(match buf.kind() {
1598 IFLA_VRF_TABLE => TableId(
1599 parse_u32(payload).context("invalid IFLA_VRF_TABLE value")?,
1600 ),
1601 kind => Other(
1602 DefaultNla::parse(buf)
1603 .context(format!("unknown NLA type {kind}"))?,
1604 ),
1605 })
1606 }
1607}
1608
1609#[derive(Debug, PartialEq, Eq, Clone)]
1610#[non_exhaustive]
1611pub enum InfoMacVlan {
1612 Unspec(Vec<u8>),
1613 Mode(u32),
1614 Flags(u16),
1615 MacAddrMode(u32),
1616 MacAddr([u8; 6]),
1617 MacAddrData(Vec<InfoMacVlan>),
1618 MacAddrCount(u32),
1619 BcQueueLen(u32),
1620 BcQueueLenUsed(u32),
1621 BcCutoff(i32),
1622 Other(DefaultNla),
1623}
1624
1625impl Nla for InfoMacVlan {
1626 fn value_len(&self) -> usize {
1627 use self::InfoMacVlan::*;
1628 match self {
1629 Unspec(bytes) => bytes.len(),
1630 Mode(_) => 4,
1631 Flags(_) => 2,
1632 MacAddrMode(_) => 4,
1633 MacAddr(_) => 6,
1634 MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
1635 MacAddrCount(_) => 4,
1636 BcQueueLen(_) => 4,
1637 BcQueueLenUsed(_) => 4,
1638 BcCutoff(_) => 4,
1639 Other(nla) => nla.value_len(),
1640 }
1641 }
1642
1643 fn emit_value(&self, buffer: &mut [u8]) {
1644 use self::InfoMacVlan::*;
1645 match self {
1646 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1647 Mode(value) => NativeEndian::write_u32(buffer, *value),
1648 Flags(value) => NativeEndian::write_u16(buffer, *value),
1649 MacAddrMode(value) => NativeEndian::write_u32(buffer, *value),
1650 MacAddr(bytes) => buffer.copy_from_slice(bytes),
1651 MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
1652 MacAddrCount(value) => NativeEndian::write_u32(buffer, *value),
1653 BcQueueLen(value) => NativeEndian::write_u32(buffer, *value),
1654 BcQueueLenUsed(value) => NativeEndian::write_u32(buffer, *value),
1655 BcCutoff(value) => NativeEndian::write_i32(buffer, *value),
1656 Other(nla) => nla.emit_value(buffer),
1657 }
1658 }
1659
1660 fn kind(&self) -> u16 {
1661 use self::InfoMacVlan::*;
1662 match self {
1663 Unspec(_) => IFLA_MACVLAN_UNSPEC,
1664 Mode(_) => IFLA_MACVLAN_MODE,
1665 Flags(_) => IFLA_MACVLAN_FLAGS,
1666 MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
1667 MacAddr(_) => IFLA_MACVLAN_MACADDR,
1668 MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
1669 MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
1670 BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
1671 BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
1672 BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
1673 Other(nla) => nla.kind(),
1674 }
1675 }
1676}
1677
1678impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVlan {
1679 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1680 use self::InfoMacVlan::*;
1681 let payload = buf.value();
1682 Ok(match buf.kind() {
1683 IFLA_MACVLAN_UNSPEC => Unspec(payload.to_vec()),
1684 IFLA_MACVLAN_MODE => Mode(
1685 parse_u32(payload)
1686 .context("invalid IFLA_MACVLAN_MODE value")?,
1687 ),
1688 IFLA_MACVLAN_FLAGS => Flags(
1689 parse_u16(payload)
1690 .context("invalid IFLA_MACVLAN_FLAGS value")?,
1691 ),
1692 IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
1693 parse_u32(payload)
1694 .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?,
1695 ),
1696 IFLA_MACVLAN_MACADDR => MacAddr(
1697 parse_mac(payload)
1698 .context("invalid IFLA_MACVLAN_MACADDR value")?,
1699 ),
1700 IFLA_MACVLAN_MACADDR_DATA => {
1701 let mut mac_data = Vec::new();
1702 let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
1703 for nla in NlasIterator::new(payload) {
1704 let nla = &nla.context(err)?;
1705 let parsed = InfoMacVlan::parse(nla).context(err)?;
1706 mac_data.push(parsed);
1707 }
1708 MacAddrData(mac_data)
1709 }
1710 IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
1711 parse_u32(payload)
1712 .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
1713 ),
1714 IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
1715 parse_u32(payload)
1716 .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
1717 ),
1718 IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
1719 parse_u32(payload)
1720 .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
1721 ),
1722 IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
1723 parse_i32(payload)
1724 .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
1725 ),
1726 kind => Other(
1727 DefaultNla::parse(buf)
1728 .context(format!("unknown NLA type {kind}"))?,
1729 ),
1730 })
1731 }
1732}
1733
1734#[derive(Debug, PartialEq, Eq, Clone)]
1735#[non_exhaustive]
1736pub enum InfoMacVtap {
1737 Unspec(Vec<u8>),
1738 Mode(u32),
1739 Flags(u16),
1740 MacAddrMode(u32),
1741 MacAddr([u8; 6]),
1742 MacAddrData(Vec<InfoMacVtap>),
1743 MacAddrCount(u32),
1744 BcQueueLen(u32),
1745 BcQueueLenUsed(u32),
1746 BcCutoff(i32),
1747 Other(DefaultNla),
1748}
1749
1750impl Nla for InfoMacVtap {
1751 fn value_len(&self) -> usize {
1752 use self::InfoMacVtap::*;
1753 match self {
1754 Unspec(bytes) => bytes.len(),
1755 Mode(_) => 4,
1756 Flags(_) => 2,
1757 MacAddrMode(_) => 4,
1758 MacAddr(_) => 6,
1759 MacAddrData(ref nlas) => nlas.as_slice().buffer_len(),
1760 MacAddrCount(_) => 4,
1761 BcQueueLen(_) => 4,
1762 BcQueueLenUsed(_) => 4,
1763 BcCutoff(_) => 4,
1764 Other(nla) => nla.value_len(),
1765 }
1766 }
1767
1768 fn emit_value(&self, buffer: &mut [u8]) {
1769 use self::InfoMacVtap::*;
1770 match self {
1771 Unspec(bytes) => buffer.copy_from_slice(bytes.as_slice()),
1772 Mode(value) => NativeEndian::write_u32(buffer, *value),
1773 Flags(value) => NativeEndian::write_u16(buffer, *value),
1774 MacAddrMode(value) => NativeEndian::write_u32(buffer, *value),
1775 MacAddr(bytes) => buffer.copy_from_slice(bytes),
1776 MacAddrData(ref nlas) => nlas.as_slice().emit(buffer),
1777 MacAddrCount(value) => NativeEndian::write_u32(buffer, *value),
1778 BcQueueLen(value) => NativeEndian::write_u32(buffer, *value),
1779 BcQueueLenUsed(value) => NativeEndian::write_u32(buffer, *value),
1780 BcCutoff(value) => NativeEndian::write_i32(buffer, *value),
1781 Other(nla) => nla.emit_value(buffer),
1782 }
1783 }
1784
1785 fn kind(&self) -> u16 {
1786 use self::InfoMacVtap::*;
1787 match self {
1788 Unspec(_) => IFLA_MACVLAN_UNSPEC,
1789 Mode(_) => IFLA_MACVLAN_MODE,
1790 Flags(_) => IFLA_MACVLAN_FLAGS,
1791 MacAddrMode(_) => IFLA_MACVLAN_MACADDR_MODE,
1792 MacAddr(_) => IFLA_MACVLAN_MACADDR,
1793 MacAddrData(_) => IFLA_MACVLAN_MACADDR_DATA,
1794 MacAddrCount(_) => IFLA_MACVLAN_MACADDR_COUNT,
1795 BcQueueLen(_) => IFLA_MACVLAN_BC_QUEUE_LEN,
1796 BcQueueLenUsed(_) => IFLA_MACVLAN_BC_QUEUE_LEN_USED,
1797 BcCutoff(_) => IFLA_MACVLAN_BC_CUTOFF,
1798 Other(nla) => nla.kind(),
1799 }
1800 }
1801}
1802
1803impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoMacVtap {
1804 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1805 use self::InfoMacVtap::*;
1806 let payload = buf.value();
1807 Ok(match buf.kind() {
1808 IFLA_MACVLAN_UNSPEC => Unspec(payload.to_vec()),
1809 IFLA_MACVLAN_MODE => Mode(
1810 parse_u32(payload)
1811 .context("invalid IFLA_MACVLAN_MODE value")?,
1812 ),
1813 IFLA_MACVLAN_FLAGS => Flags(
1814 parse_u16(payload)
1815 .context("invalid IFLA_MACVLAN_FLAGS value")?,
1816 ),
1817 IFLA_MACVLAN_MACADDR_MODE => MacAddrMode(
1818 parse_u32(payload)
1819 .context("invalid IFLA_MACVLAN_MACADDR_MODE value")?,
1820 ),
1821 IFLA_MACVLAN_MACADDR => MacAddr(
1822 parse_mac(payload)
1823 .context("invalid IFLA_MACVLAN_MACADDR value")?,
1824 ),
1825 IFLA_MACVLAN_MACADDR_DATA => {
1826 let mut mac_data = Vec::new();
1827 let err = "failed to parse IFLA_MACVLAN_MACADDR_DATA";
1828 for nla in NlasIterator::new(payload) {
1829 let nla = &nla.context(err)?;
1830 let parsed = InfoMacVtap::parse(nla).context(err)?;
1831 mac_data.push(parsed);
1832 }
1833 MacAddrData(mac_data)
1834 }
1835 IFLA_MACVLAN_MACADDR_COUNT => MacAddrCount(
1836 parse_u32(payload)
1837 .context("invalid IFLA_MACVLAN_MACADDR_COUNT value")?,
1838 ),
1839 IFLA_MACVLAN_BC_QUEUE_LEN => BcQueueLen(
1840 parse_u32(payload)
1841 .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN value")?,
1842 ),
1843 IFLA_MACVLAN_BC_QUEUE_LEN_USED => BcQueueLenUsed(
1844 parse_u32(payload)
1845 .context("invalid IFLA_MACVLAN_BC_QUEUE_LEN_USED value")?,
1846 ),
1847 IFLA_MACVLAN_BC_CUTOFF => BcCutoff(
1848 parse_i32(payload)
1849 .context("invalid IFLA_MACVLAN_BC_CUTOFF value")?,
1850 ),
1851 kind => Other(
1852 DefaultNla::parse(buf)
1853 .context(format!("unknown NLA type {kind}"))?,
1854 ),
1855 })
1856 }
1857}
1858
1859#[derive(Debug, PartialEq, Eq, Clone)]
1860#[non_exhaustive]
1861pub enum VlanQosMapping {
1862 Unspec(Vec<u8>),
1863 Mapping { from: u32, to: u32 },
1864 Other(DefaultNla),
1865}
1866
1867impl Nla for VlanQosMapping {
1868 fn value_len(&self) -> usize {
1869 match self {
1870 VlanQosMapping::Unspec(bytes) => bytes.len(),
1871 VlanQosMapping::Mapping { .. } => 8,
1872 VlanQosMapping::Other(nla) => nla.value_len(),
1873 }
1874 }
1875
1876 fn kind(&self) -> u16 {
1877 match self {
1878 VlanQosMapping::Unspec(_) => IFLA_VLAN_QOS_UNSPEC,
1879 VlanQosMapping::Mapping { .. } => IFLA_VLAN_QOS_MAPPING,
1880 VlanQosMapping::Other(nla) => nla.kind(),
1881 }
1882 }
1883
1884 fn emit_value(&self, buffer: &mut [u8]) {
1885 use VlanQosMapping::*;
1886 match self {
1887 Unspec(payload) => buffer.copy_from_slice(payload),
1888 Mapping { from, to } => {
1889 NativeEndian::write_u32(buffer, *from);
1890 NativeEndian::write_u32(&mut buffer[4..], *to);
1891 }
1892 Other(nla) => nla.emit_value(buffer),
1893 }
1894 }
1895}
1896
1897impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
1898 for VlanQosMapping
1899{
1900 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
1901 use VlanQosMapping::*;
1902 let payload = buf.value();
1903 Ok(match buf.kind() {
1904 IFLA_VLAN_QOS_UNSPEC => Unspec(payload.to_vec()),
1905 IFLA_VLAN_QOS_MAPPING => Mapping {
1906 from: parse_u32(&payload[..4])
1907 .context("expected u32 from value")?,
1908 to: parse_u32(&payload[4..])
1909 .context("expected u32 to value")?,
1910 },
1911 kind => Other(
1912 DefaultNla::parse(buf)
1913 .context(format!("unknown NLA type {kind}"))?,
1914 ),
1915 })
1916 }
1917}
1918
1919#[cfg(test)]
1920mod tests {
1921 use super::*;
1922 use crate::{
1923 nlas::link::{bond::*, Nla},
1924 LinkHeader, LinkMessage,
1925 };
1926 use netlink_packet_utils::traits::Emitable;
1927 use std::net::{Ipv4Addr, Ipv6Addr};
1928
1929 #[rustfmt::skip]
1930 static BRIDGE: [u8; 424] = [
1931 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, ];
2139
2140 lazy_static! {
2141 static ref BRIDGE_INFO: Vec<InfoBridge> = vec![
2142 InfoBridge::HelloTimer(35),
2143 InfoBridge::TcnTimer(0),
2144 InfoBridge::TopologyChangeTimer(0),
2145 InfoBridge::GcTimer(14261),
2146 InfoBridge::ForwardDelay(199),
2147 InfoBridge::HelloTime(199),
2148 InfoBridge::MaxAge(1999),
2149 InfoBridge::AgeingTime(29999),
2150 InfoBridge::StpState(1),
2151 InfoBridge::Priority(0x8000),
2152 InfoBridge::VlanFiltering(0),
2153 InfoBridge::GroupFwdMask(0),
2154 InfoBridge::BridgeId((128, [0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e])),
2155 InfoBridge::RootId((128, [0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e])),
2156 InfoBridge::RootPort(0),
2157 InfoBridge::RootPathCost(0),
2158 InfoBridge::TopologyChange(0),
2159 InfoBridge::TopologyChangeDetected(0),
2160 InfoBridge::GroupAddr([0x01, 0x80, 0xc2, 0x00, 0x00, 0x00]),
2161 InfoBridge::VlanProtocol(33024),
2162 InfoBridge::VlanDefaultPvid(1),
2163 InfoBridge::VlanStatsEnabled(0),
2164 InfoBridge::MulticastRouter(1),
2165 InfoBridge::MulticastSnooping(1),
2166 InfoBridge::MulticastQueryUseIfaddr(0),
2167 InfoBridge::MulticastQuerier(0),
2168 InfoBridge::MulticastStatsEnabled(0),
2169 InfoBridge::MulticastHashElasticity(4),
2170 InfoBridge::MulticastHashMax(512),
2171 InfoBridge::MulticastLastMemberCount(2),
2172 InfoBridge::MulticastStartupQueryCount(2),
2173 InfoBridge::MulticastIgmpVersion(2),
2174 InfoBridge::MulticastMldVersion(1),
2175 InfoBridge::MulticastLastMemberInterval(99),
2176 InfoBridge::MulticastMembershipInterval(25999),
2177 InfoBridge::MulticastQuerierInterval(25499),
2178 InfoBridge::MulticastQueryInterval(12499),
2179 InfoBridge::MulticastQueryResponseInterval(999),
2180 InfoBridge::MulticastStartupQueryInterval(3124),
2181 InfoBridge::NfCallIpTables(0),
2182 InfoBridge::NfCallIp6Tables(0),
2183 InfoBridge::NfCallArpTables(0),
2184 InfoBridge::VlanStatsPerHost(1),
2185 InfoBridge::MultiBoolOpt(0),
2186 ];
2187 }
2188
2189 #[test]
2190 fn parse_info_kind() {
2191 let info_kind_nla = NlaBuffer::new_checked(&BRIDGE[..12]).unwrap();
2192 let parsed = InfoKind::parse(&info_kind_nla).unwrap();
2193 assert_eq!(parsed, InfoKind::Bridge);
2194 }
2195
2196 #[test]
2197 fn parse_info_bridge() {
2198 let nlas = NlasIterator::new(&BRIDGE[16..]);
2199 for nla in nlas.map(|nla| nla.unwrap()) {
2200 InfoBridge::parse(&nla).unwrap();
2201 }
2202 }
2203
2204 #[rustfmt::skip]
2205 #[test]
2206 fn parse_veth_info() {
2207 let data = [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,
2227 0x08, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00];
2231 let nla = NlaBuffer::new_checked(&data[..]).unwrap();
2232 let parsed = VecInfo::parse(&nla).unwrap().0;
2233 let expected = vec![
2234 Info::Kind(InfoKind::Veth),
2235 Info::Data(InfoData::Veth(VethInfo::Peer(LinkMessage {
2236 header: LinkHeader {
2237 interface_family: 0,
2238 index: 0,
2239 link_layer_type: ARPHRD_NETROM,
2240 flags: 0,
2241 change_mask: 0,
2242 },
2243 nlas: vec![
2244 Nla::IfName("vethc0e60d6".to_string()),
2245 Nla::TxQueueLen(0),
2246 ],
2247 }))),
2248 ];
2249 assert_eq!(expected, parsed);
2250 }
2251
2252 #[rustfmt::skip]
2253 #[test]
2254 fn parse_info_bondport() {
2255 let data = [0x09, 0x00, 0x04, 0x00, 0x62, 0x6f, 0x6e, 0x64, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x32, 0x00, 0x00, 0x00];
2270 let nla = NlaBuffer::new_checked(&data[..]).unwrap();
2271 let parsed = VecInfo::parse(&nla).unwrap().0;
2272 let expected = vec![
2273 Info::PortKind(InfoPortKind::Bond),
2274 Info::PortData(InfoPortData::BondPort(vec![InfoBondPort::QueueId(0),
2275 InfoBondPort::Prio(50),
2276 ])),
2277 ];
2278 assert_eq!(expected, parsed);
2279 }
2280
2281 #[rustfmt::skip]
2282 #[test]
2283 fn parse_info_bond() {
2284 let data = [0x08, 0x00, 0x01, 0x00, 0x62, 0x6f, 0x6e, 0x64, 0x80, 0x00, 0x02, 0x00, 0x05, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00, 0x64, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x00, 0x01, 0x00, 0x09, 0x09, 0x09, 0x09, 0x18, 0x00, 0x1f, 0x00, 0x14, 0x00, 0x00, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2322 0x00, 0x00, 0x00, 0x00,
2323 0x00, 0x00, 0x00, 0x01,
2324
2325 0x08, 0x00, 0x1c, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x17, 0x00, 0x06, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
2347 0x00, 0x00];
2348 let nla = NlaBuffer::new_checked(&data[..]).unwrap();
2349 let parsed = VecInfo::parse(&nla).unwrap().0;
2350 let expected = vec![
2351 Info::Kind(InfoKind::Bond),
2352 Info::Data(InfoData::Bond(vec![InfoBond::Mode(4),
2353 InfoBond::MiiMon(50),
2354 InfoBond::UpDelay(100),
2355 InfoBond::DownDelay(100),
2356 InfoBond::ArpIpTarget(vec!(Ipv4Addr::new(1, 2, 3, 4),
2357 Ipv4Addr::new(9, 9, 9, 9))),
2358 InfoBond::NsIp6Target(vec!(Ipv6Addr::new(0xfd01, 0, 0, 0, 0, 0, 0, 1))),
2359 InfoBond::PeerNotifDelay(200),
2360 InfoBond::MinLinks(3),
2361 InfoBond::AdInfo(vec!(BondAdInfo::Aggregator(16),
2362 BondAdInfo::NumPorts(2),
2363 BondAdInfo::PartnerMac([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]))),
2364 ])),
2365 ];
2366 assert_eq!(expected, parsed);
2367 }
2368
2369 #[rustfmt::skip]
2370 static IPVLAN: [u8; 32] = [
2371 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, ];
2388
2389 lazy_static! {
2390 static ref IPVLAN_INFO: Vec<InfoIpVlan> = vec![
2391 InfoIpVlan::Mode(1), InfoIpVlan::Flags(2), ];
2394 }
2395
2396 #[test]
2397 fn parse_info_ipvlan() {
2398 let nla = NlaBuffer::new_checked(&IPVLAN[..]).unwrap();
2399 let parsed = VecInfo::parse(&nla).unwrap().0;
2400 let expected = vec![
2401 Info::Kind(InfoKind::IpVlan),
2402 Info::Data(InfoData::IpVlan(IPVLAN_INFO.clone())),
2403 ];
2404 assert_eq!(expected, parsed);
2405 }
2406
2407 #[test]
2408 fn emit_info_ipvlan() {
2409 let nlas = vec![
2410 Info::Kind(InfoKind::IpVlan),
2411 Info::Data(InfoData::IpVlan(IPVLAN_INFO.clone())),
2412 ];
2413
2414 assert_eq!(nlas.as_slice().buffer_len(), 32);
2415
2416 let mut vec = vec![0xff; 32];
2417 nlas.as_slice().emit(&mut vec);
2418 assert_eq!(&vec[..], &IPVLAN[..]);
2419 }
2420
2421 #[rustfmt::skip]
2422 static MACVLAN: [u8; 24] = [
2423 0x0c, 0x00, 0x01, 0x00, 0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, ];
2432
2433 lazy_static! {
2434 static ref MACVLAN_INFO: Vec<InfoMacVlan> = vec![
2435 InfoMacVlan::Mode(4), ];
2437 }
2438
2439 #[test]
2440 fn parse_info_macvlan() {
2441 let nla = NlaBuffer::new_checked(&MACVLAN[..]).unwrap();
2442 let parsed = VecInfo::parse(&nla).unwrap().0;
2443 let expected = vec![
2444 Info::Kind(InfoKind::MacVlan),
2445 Info::Data(InfoData::MacVlan(MACVLAN_INFO.clone())),
2446 ];
2447 assert_eq!(expected, parsed);
2448 }
2449
2450 #[test]
2451 fn emit_info_macvlan() {
2452 let nlas = vec![
2453 Info::Kind(InfoKind::MacVlan),
2454 Info::Data(InfoData::MacVlan(MACVLAN_INFO.clone())),
2455 ];
2456
2457 assert_eq!(nlas.as_slice().buffer_len(), 24);
2458
2459 let mut vec = vec![0xff; 24];
2460 nlas.as_slice().emit(&mut vec);
2461 assert_eq!(&vec[..], &MACVLAN[..]);
2462 }
2463
2464 #[rustfmt::skip]
2465 static MACVLAN_BC: [u8; 48] = [
2466 0x0c, 0x00, 0x01, 0x00, 0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x24, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0xff, 0xff, 0xff, 0xff, ];
2487
2488 lazy_static! {
2489 static ref MACVLAN_INFO_BC: Vec<InfoMacVlan> = vec![
2490 InfoMacVlan::Mode(2), InfoMacVlan::BcQueueLen(1000),
2492 InfoMacVlan::BcQueueLenUsed(1000),
2493 InfoMacVlan::BcCutoff(-1),
2494 ];
2495 }
2496
2497 #[test]
2498 fn parse_info_macvlan_bc() {
2499 let nla = NlaBuffer::new_checked(&MACVLAN_BC[..]).unwrap();
2500 let parsed = VecInfo::parse(&nla).unwrap().0;
2501 let expected = vec![
2502 Info::Kind(InfoKind::MacVlan),
2503 Info::Data(InfoData::MacVlan(MACVLAN_INFO_BC.clone())),
2504 ];
2505 assert_eq!(expected, parsed);
2506 }
2507
2508 #[test]
2509 fn emit_info_macvlan_bc() {
2510 let nlas = vec![
2511 Info::Kind(InfoKind::MacVlan),
2512 Info::Data(InfoData::MacVlan(MACVLAN_INFO_BC.clone())),
2513 ];
2514
2515 assert_eq!(nlas.as_slice().buffer_len(), 48);
2516
2517 let mut vec = vec![0xff; 48];
2518 nlas.as_slice().emit(&mut vec);
2519 assert_eq!(&vec[..], &MACVLAN_BC[..]);
2520 }
2521
2522 lazy_static! {
2523 static ref XFRMTUN_INFO: Vec<InfoXfrmTun> = vec![
2524 InfoXfrmTun::IfId(4), ];
2526 }
2527 #[rustfmt::skip]
2528 static XFRMTUN: [u8; 24] = [
2529 9, 0, 1, 0, 120,102,114,109,
2530 0, 0, 0, 0, 12, 0, 2, 0,
2531 8, 0, 2, 0, 4, 0, 0, 0
2532 ];
2533 #[test]
2534 fn emit_info_xfrmtun() {
2535 let nlas = vec![
2536 Info::Kind(InfoKind::Xfrm),
2537 Info::Data(InfoData::Xfrm(XFRMTUN_INFO.clone())),
2538 ];
2539
2540 assert_eq!(nlas.as_slice().buffer_len(), 24);
2541
2542 let mut vec = vec![0xff; 24];
2543 nlas.as_slice().emit(&mut vec);
2544 assert_eq!(&vec[..], &XFRMTUN[..]);
2545 }
2546
2547 #[rustfmt::skip]
2548 static MACVLAN_SOURCE_SET: [u8; 84] = [
2549 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, ];
2583
2584 lazy_static! {
2585 static ref MACVLAN_SOURCE_SET_INFO: Vec<InfoMacVlan> = vec![
2586 InfoMacVlan::MacAddrMode(3), InfoMacVlan::MacAddrData(vec![
2588 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x88, 0xd7,]),
2589 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x99, 0x32,]),
2590 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x87, 0x45,]),
2591 InfoMacVlan::MacAddr([0x22, 0xf5, 0x54, 0x09, 0x11, 0x45,]),
2592 ]),
2593 InfoMacVlan::Mode(16), ];
2595 }
2596
2597 #[test]
2598 fn parse_info_macvlan_source_set() {
2599 let nla = NlaBuffer::new_checked(&MACVLAN_SOURCE_SET[..]).unwrap();
2600 let parsed = VecInfo::parse(&nla).unwrap().0;
2601 let expected = vec![
2602 Info::Kind(InfoKind::MacVlan),
2603 Info::Data(InfoData::MacVlan(MACVLAN_SOURCE_SET_INFO.clone())),
2604 ];
2605 assert_eq!(expected, parsed);
2606 }
2607
2608 #[test]
2609 fn emit_info_macvlan_source_set() {
2610 let nlas = vec![
2611 Info::Kind(InfoKind::MacVlan),
2612 Info::Data(InfoData::MacVlan(MACVLAN_SOURCE_SET_INFO.clone())),
2613 ];
2614
2615 assert_eq!(nlas.as_slice().buffer_len(), 84);
2616
2617 let mut vec = vec![0xff; 84];
2618 nlas.as_slice().emit(&mut vec);
2619 assert_eq!(&vec[..], &MACVLAN_SOURCE_SET[..]);
2620 }
2621
2622 #[test]
2623 fn parse() {
2624 let nla = NlaBuffer::new_checked(&BRIDGE[..]).unwrap();
2625 let parsed = VecInfo::parse(&nla).unwrap().0;
2626 assert_eq!(parsed.len(), 2);
2627 assert_eq!(parsed[0], Info::Kind(InfoKind::Bridge));
2628 if let Info::Data(InfoData::Bridge(nlas)) = parsed[1].clone() {
2629 assert_eq!(nlas.len(), BRIDGE_INFO.len());
2630 for (expected, parsed) in BRIDGE_INFO.iter().zip(nlas) {
2631 assert_eq!(*expected, parsed);
2632 }
2633 } else {
2634 panic!(
2635 "expected Info::Data(InfoData::Bridge(_) got {:?}",
2636 parsed[1]
2637 )
2638 }
2639 }
2640
2641 #[test]
2642 fn emit() {
2643 let nlas = vec![
2644 Info::Kind(InfoKind::Bridge),
2645 Info::Data(InfoData::Bridge(BRIDGE_INFO.clone())),
2646 ];
2647
2648 assert_eq!(nlas.as_slice().buffer_len(), 424);
2649
2650 let mut vec = vec![0xff; 424];
2651 nlas.as_slice().emit(&mut vec);
2652 assert_eq!(&vec[..], &BRIDGE[..]);
2653 }
2654
2655 #[rustfmt::skip]
2656 static VLAN: [u8; 68] = [
2657 0x09, 0x00, 0x01, 0x00, 0x76, 0x6c, 0x61, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ];
2684
2685 lazy_static! {
2686 static ref VLAN_INFO: Vec<InfoVlan> = vec![
2687 InfoVlan::Id(75),
2688 InfoVlan::EgressQos(vec![VlanQosMapping::Mapping {
2689 from: 3,
2690 to: 4
2691 }]),
2692 InfoVlan::IngressQos(vec![
2693 VlanQosMapping::Mapping { from: 0, to: 1 },
2694 VlanQosMapping::Mapping { from: 1, to: 2 }
2695 ]),
2696 ];
2697 }
2698
2699 #[test]
2700 fn parse_info_vlan() {
2701 let nla = NlaBuffer::new_checked(&VLAN[..]).unwrap();
2702 let parsed = VecInfo::parse(&nla).unwrap().0;
2703 let expected = vec![
2704 Info::Kind(InfoKind::Vlan),
2705 Info::Data(InfoData::Vlan(VLAN_INFO.clone())),
2706 ];
2707 assert_eq!(expected, parsed);
2708 }
2709
2710 #[test]
2711 fn emit_info_vlan() {
2712 let nlas = vec![
2713 Info::Kind(InfoKind::Vlan),
2714 Info::Data(InfoData::Vlan(VLAN_INFO.clone())),
2715 ];
2716
2717 assert_eq!(nlas.as_slice().buffer_len(), VLAN.len());
2718
2719 let mut vec = vec![0xff; VLAN.len()];
2720 nlas.as_slice().emit(&mut vec);
2721 assert_eq!(&vec[..], &VLAN[..]);
2722 }
2723
2724 #[rustfmt::skip]
2725 static VXLAN: [u8; 32] = [
2726 0x0a, 0x00, 0x01, 0x00, 0x76, 0x78, 0x6C, 0x61, 0x6E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0F, 0x00, 0x12, 0xB5, 0x00, 0x00 ];
2741
2742 lazy_static! {
2743 static ref VXLAN_INFO: Vec<InfoVxlan> =
2744 vec![InfoVxlan::Id(10), InfoVxlan::Port(4789),];
2745 }
2746
2747 #[test]
2748 fn parse_info_vxlan() {
2749 let nla = NlaBuffer::new_checked(&VXLAN[..]).unwrap();
2750 let parsed = VecInfo::parse(&nla).unwrap().0;
2751 let expected = vec![
2752 Info::Kind(InfoKind::Vxlan),
2753 Info::Data(InfoData::Vxlan(VXLAN_INFO.clone())),
2754 ];
2755 assert_eq!(expected, parsed);
2756 }
2757
2758 #[test]
2759 fn emit_info_vxlan() {
2760 let nlas = vec![
2761 Info::Kind(InfoKind::Vxlan),
2762 Info::Data(InfoData::Vxlan(VXLAN_INFO.clone())),
2763 ];
2764
2765 assert_eq!(nlas.as_slice().buffer_len(), VXLAN.len());
2766
2767 let mut vec = vec![0xff; VXLAN.len()];
2768 nlas.as_slice().emit(&mut vec);
2769 assert_eq!(&vec[..], &VXLAN[..]);
2770 }
2771
2772 lazy_static! {
2773 static ref VXLAN_INFO_WITH_PORT_RANGE: Vec<InfoVxlan> =
2774 vec![InfoVxlan::Id(10), InfoVxlan::PortRange((9000, 9050)),];
2775 }
2776
2777 #[rustfmt::skip]
2778 static VXLAN_WITH_PORT_RANGE: [u8; 32] = [
2779 0x0a, 0x00, 0x01, 0x00, 0x76, 0x78, 0x6C, 0x61, 0x6E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x23, 0x28, 0x23, 0x5a ];
2794
2795 #[test]
2796 fn emit_info_vxlan_with_port_range() {
2797 let nlas = vec![
2798 Info::Kind(InfoKind::Vxlan),
2799 Info::Data(InfoData::Vxlan(VXLAN_INFO_WITH_PORT_RANGE.clone())),
2800 ];
2801
2802 assert_eq!(nlas.as_slice().buffer_len(), VXLAN_WITH_PORT_RANGE.len());
2803
2804 let mut vec = vec![0xff; VXLAN_WITH_PORT_RANGE.len()];
2805 nlas.as_slice().emit(&mut vec);
2806 assert_eq!(&vec[..], &VXLAN_WITH_PORT_RANGE[..]);
2807 }
2808
2809 #[test]
2810 fn parse_info_vxlan_with_port_range() {
2811 let nla = NlaBuffer::new_checked(&VXLAN_WITH_PORT_RANGE[..]).unwrap();
2812 let parsed = VecInfo::parse(&nla).unwrap().0;
2813 let expected = vec![
2814 Info::Kind(InfoKind::Vxlan),
2815 Info::Data(InfoData::Vxlan(VXLAN_INFO_WITH_PORT_RANGE.clone())),
2816 ];
2817 assert_eq!(expected, parsed);
2818 }
2819
2820 #[rustfmt::skip]
2821 static MACSEC: [u8; 120] = [
2822 0x0b, 0x00, 0x01, 0x00, 0x6d, 0x61, 0x63, 0x73, 0x65, 0x63, 0x00, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x76, 0x83, 0x22, 0x9e, 0xd6, 0xfd, 0x00, 0x0b, 0x05, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00 ];
2888
2889 lazy_static! {
2890 static ref MACSEC_INFO: Vec<InfoMacSec> = vec![
2891 InfoMacSec::Sci(792912632635097974),
2892 InfoMacSec::IcvLen(16),
2893 #[allow(deprecated)]
2894 InfoMacSec::CipherSuite(MacSecCipherId::DefaultGcmAes128),
2895 InfoMacSec::EncodingSa(0),
2896 InfoMacSec::Encrypt(1),
2897 InfoMacSec::Protect(1),
2898 InfoMacSec::IncSci(1),
2899 InfoMacSec::Es(0),
2900 InfoMacSec::Scb(0),
2901 InfoMacSec::ReplayProtect(0),
2902 InfoMacSec::Validation(MacSecValidation::Strict),
2903 InfoMacSec::Offload(MacSecOffload::Off),
2904 ];
2905 }
2906
2907 #[test]
2908 fn parse_info_macsec() {
2909 let nla = NlaBuffer::new_checked(&MACSEC[..]).unwrap();
2910 let parsed = VecInfo::parse(&nla).unwrap().0;
2911 let expected = vec![
2912 Info::Kind(InfoKind::MacSec),
2913 Info::Data(InfoData::MacSec(MACSEC_INFO.clone())),
2914 ];
2915 assert_eq!(expected, parsed);
2916 }
2917
2918 #[test]
2919 fn emit_info_macsec() {
2920 let nlas = vec![
2921 Info::Kind(InfoKind::MacSec),
2922 Info::Data(InfoData::MacSec(MACSEC_INFO.clone())),
2923 ];
2924
2925 assert_eq!(nlas.as_slice().buffer_len(), MACSEC.len());
2926
2927 let mut vec = vec![0xff; MACSEC.len()];
2928 nlas.as_slice().emit(&mut vec);
2929 assert_eq!(&vec[..], &MACSEC[..]);
2930 }
2931}