netlink_packet_route/rtnl/link/nlas/
link_infos.rs

1// SPDX-License-Identifier: MIT
2
3use 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
99// We cannot `impl Parseable<_> for Info` because some attributes
100// depend on each other. To parse IFLA_INFO_DATA we first need to
101// parse the preceding IFLA_INFO_KIND for example.
102//
103// Moreover, with cannot `impl Parseable for Vec<Info>` due to the
104// orphan rule: `Parseable` and `Vec<_>` are both defined outside of
105// this crate. Thus, we create this internal VecInfo struct that wraps
106// `Vec<Info>` and allows us to circumvent the orphan rule.
107//
108// The downside is that this impl will not be exposed.
109impl<'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// https://elixir.bootlin.com/linux/v5.9.8/source/drivers/net/vxlan.c#L3332
690#[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// https://elixir.bootlin.com/linux/latest/source/net/8021q/vlan_netlink.c#L21
961#[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, // L = 11
1932        0x01, 0x00, // T = 1 (IFLA_INFO_KIND)
1933        0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, // V = "bridge"
1934        0x00, // padding
1935
1936        0x9c, 0x01, // L = 412
1937        0x02, 0x00, // T = 2 (IFLA_INFO_DATA)
1938
1939            0x0c, 0x00, // L = 12
1940            0x10, 0x00, // T = 16 (IFLA_BR_HELLO_TIMER)
1941            0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 35
1942
1943            0x0c, 0x00, // L = 12
1944            0x11, 0x00, // T = 17 (IFLA_BR_TCN_TIMER)
1945            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 0
1946
1947            0x0c, 0x00, // L = 12
1948            0x12, 0x00, // T = 18 (IFLA_BR_TOPOLOGY_CHANGE_TIMER)
1949            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 0
1950
1951            0x0c, 0x00, //  L = 12
1952            0x13, 0x00, // T = 19 (IFLA_BR_GC_TIMER)
1953            0xb5, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 14261 (0x37b5)
1954
1955            0x08, 0x00, // L = 8
1956            0x01, 0x00, // T = 1 (IFLA_BR_FORWARD_DELAY)
1957            0xc7, 0x00, 0x00, 0x00, // V = 199
1958
1959            0x08, 0x00, // L = 8
1960            0x02, 0x00, // T = 2 (IFLA_BR_HELLO_TIME)
1961            0xc7, 0x00, 0x00, 0x00, // V = 199
1962
1963            0x08, 0x00, // L = 8
1964            0x03, 0x00, // T = 3 (IFLA_BR_MAX_AGE)
1965            0xcf, 0x07, 0x00, 0x00, // V = 1999 (0x07cf)
1966
1967            0x08, 0x00, // L = 8
1968            0x04, 0x00, // T = 4 (IFLA_BR_AGEING_TIME)
1969            0x2f, 0x75, 0x00, 0x00, // V = 29999 (0x752f)
1970
1971            0x08, 0x00, // L = 8
1972            0x05, 0x00, // T = 5 (IFLA_BR_STP_STATE)
1973            0x01, 0x00, 0x00, 0x00, // V = 1
1974
1975            0x06, 0x00, // L = 6
1976            0x06, 0x00, // T = 6 (IFLA_BR_PRIORITY)
1977            0x00, 0x80, // V =  32768 (0x8000)
1978            0x00, 0x00, // Padding
1979
1980            0x05, 0x00, // L = 5
1981            0x07, 0x00, // T = 7 (IFLA_BR_VLAN_FILTERING)
1982            0x00, // V = 0
1983            0x00, 0x00, 0x00, // Padding
1984
1985            0x06, 0x00, // L = 6
1986            0x09, 0x00, // T = 9 (IFLA_BR_GROUP_FWD_MASK)
1987            0x00, 0x00, // V = 0
1988            0x00, 0x00, // Padding
1989
1990            0x0c, 0x00, // L = 12
1991            0x0b, 0x00, // T = 11 (IFLA_BR_BRIDGE_ID)
1992            0x80, 0x00, // V (priority) = 128 (0x80)
1993            0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e, // V (address) = 52:54:00:d7:19:3e
1994
1995            0x0c, 0x00, // L = 12
1996            0x0a, 0x00, // T = 10 (IFLA_BR_ROOT_ID)
1997            0x80, 0x00, // V (priority) = 128 (0x80)
1998            0x52, 0x54, 0x00, 0xd7, 0x19, 0x3e, // V (address) = 52:54:00:d7:19:3e
1999
2000            0x06, 0x00, // L = 6
2001            0x0c, 0x00, // T = 12 (IFLA_BR_ROOT_PORT)
2002            0x00, 0x00, // V = 0
2003            0x00, 0x00, // Padding
2004
2005            0x08, 0x00, // L = 8
2006            0x0d, 0x00, // T = 13 (IFLA_BR_ROOT_PATH_COST)
2007            0x00, 0x00, 0x00, 0x00, // V = 0
2008
2009            0x05, 0x00, // L = 5
2010            0x0e, 0x00, // T = 14 (IFLA_BR_TOPOLOGY_CHANGE)
2011            0x00, // V = 0
2012            0x00, 0x00, 0x00, // Padding
2013
2014            0x05, 0x00, // L = 5
2015            0x0f, 0x00, // T = 15 (IFLA_BR_TOPOLOGY_CHANGE_DETECTED)
2016            0x00, // V = 0
2017            0x00, 0x00, 0x00, // Padding
2018
2019            0x0a, 0x00, // L = 10
2020            0x14, 0x00, // T = 20 (IFLA_BR_GROUP_ADDR)
2021            0x01, 0x80, 0xc2, 0x00, 0x00, 0x00, // V = 01:80:c2:00:00:00
2022            0x00, 0x00, // Padding
2023
2024            0x06, 0x00, // L = 6
2025            0x08, 0x00, // T = 8 (IFLA_BR_VLAN_PROTOCOL)
2026            0x81, 0x00, // V = 33024 (big-endian)
2027            0x00, 0x00, // Padding
2028
2029            0x06, 0x00, // L = 6
2030            0x27, 0x00, // T = 39 (IFLA_BR_VLAN_DEFAULT_PVID)
2031            0x01, 0x00, // V = 1
2032            0x00, 0x00, // Padding
2033
2034            0x05, 0x00, // L = 5
2035            0x29, 0x00, // T = 41 (IFLA_BR_VLAN_STATS_ENABLED)
2036            0x00, // V = 0
2037            0x00, 0x00, 0x00, // Padding
2038
2039            0x05, 0x00, // L = 5
2040            0x16, 0x00, // T = 22 (IFLA_BR_MCAST_ROUTER)
2041            0x01, // V = 1
2042            0x00, 0x00, 0x00, // Padding
2043
2044            0x05, 0x00, // L = 5
2045            0x17, 0x00, // T = 23 (IFLA_BR_MCAST_SNOOPING)
2046            0x01, // V = 1
2047            0x00, 0x00, 0x00, // Padding
2048
2049            0x05, 0x00, // L = 5
2050            0x18, 0x00, // T = 24 (IFLA_BR_MCAST_QUERY_USE_IFADDR)
2051            0x00, // V = 0
2052            0x00, 0x00, 0x00, // Padding
2053
2054            0x05, 0x00, // L = 5
2055            0x19, 0x00, // T = 25 (IFLA_BR_MCAST_QUERIER)
2056            0x00, // V = 0
2057            0x00, 0x00, 0x00, // Padding
2058
2059            0x05, 0x00, // L = 5
2060            0x2a, 0x00, // T = 42 (IFLA_BR_MCAST_STATS_ENABLED)
2061            0x00, // V = 0
2062            0x00, 0x00, 0x00, // Padding
2063
2064            0x08, 0x00, // L = 8
2065            0x1a, 0x00, // T = 26 (IFLA_BR_MCAST_HASH_ELASTICITY)
2066            0x04, 0x00, 0x00, 0x00, // V = 4
2067
2068            0x08, 0x00, // L = 8
2069            0x1b, 0x00, // T = 27 (IFLA_BR_MCAST_HASH_MAX)
2070            0x00, 0x02, 0x00, 0x00, // V = 512 (0x0200)
2071
2072            0x08, 0x00, // L = 8
2073            0x1c, 0x00, // T = 28 (IFLA_BR_MCAST_LAST_MEMBER_CNT)
2074            0x02, 0x00, 0x00, 0x00, // V = 2
2075
2076            0x08, 0x00, // L = 8
2077            0x1d, 0x00, // T = 29 (IFLA_BR_MCAST_STARTUP_QUERY_CNT)
2078            0x02, 0x00, 0x00, 0x00, // V = 2
2079
2080            0x05, 0x00, // L = 5
2081            0x2b, 0x00, // T = 43 (IFLA_BR_MCAST_IGMP_VERSION)
2082            0x02, // V = 2
2083            0x00, 0x00, 0x00, // Padding
2084
2085            0x05, 0x00, // L = 5
2086            0x2c, 0x00, // T = 44 (IFLA_BR_MCAST_MLD_VERSION)
2087            0x01, // V = 1
2088            0x00, 0x00, 0x00, // Padding
2089
2090            0x0c, 0x00, // L = 12
2091            0x1e, 0x00, // T = 30 (IFLA_BR_MCAST_LAST_MEMBER_INTVL)
2092            0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 99
2093
2094            0x0c, 0x00, // L = 12
2095            0x1f, 0x00, // T = 31 (IFLA_BR_MCAST_MEMBERSHIP_INTVL)
2096            0x8f, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 25999 (0x658f)
2097
2098            0x0c, 0x00, // L = 12
2099            0x20, 0x00, // T = 32 (IFLA_BR_MCAST_QUERIER_INTVL)
2100            0x9b, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 25499 (0x639b)
2101
2102            0x0c, 0x00, // L = 12
2103            0x21, 0x00, // T = 33 (IFLA_BR_MCAST_QUERY_INTVL)
2104            0xd3, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 12499 (0x30d3)
2105
2106            0x0c, 0x00, // L = 12
2107            0x22, 0x00, // T = 34 (IFLA_BR_MCAST_QUERY_RESPONSE_INTVL)
2108            0xe7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 999 (0x03e7)
2109
2110            0x0c, 0x00, // L = 12
2111            0x23, 0x00, // T = 35 (IFLA_BR_MCAST_STARTUP_QUERY_INTVL)
2112            0x34, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // V = 3124 (0x0c34)
2113
2114            0x05, 0x00, // L = 5
2115            0x24, 0x00, // T = 36 (IFLA_BR_NF_CALL_IPTABLES)
2116            0x00, // V = 0
2117            0x00, 0x00, 0x00, // Padding
2118
2119            0x05, 0x00, // L = 5
2120            0x25, 0x00, // T = 37 (IFLA_BR_NF_CALL_IP6TABLES)
2121            0x00, // V = 0
2122            0x00, 0x00, 0x00, // Padding
2123
2124            0x05, 0x00, // L = 5
2125            0x26, 0x00, // T = 38 (IFLA_BR_NF_CALL_ARPTABLES)
2126            0x00, // V = 0
2127            0x00, 0x00, 0x00, // Padding
2128
2129            0x05, 0x00, // L = 5
2130            0x2d, 0x00, // T = 45 (IFLA_BR_VLAN_STATS_PER_PORT)
2131            0x01, // V = 1
2132            0x00, 0x00, 0x00, // Padding
2133
2134            0x0c, 0x00, // L = 12
2135            0x2e, 0x00, // T = 46 (IFLA_BR_MULTI_BOOLOPT)
2136            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // V = 0
2137
2138    ];
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, // length = 8
2208            0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2209            0x76, 0x65, 0x74, 0x68, // VETH
2210
2211            0x30, 0x00, // length = 48
2212            0x02, 0x00, // type = IFLA_INFO_DATA
2213
2214                0x2c, 0x00, // length = 44
2215                0x01, 0x00, // type = VETH_INFO_PEER
2216                // The data a NEWLINK message
2217                0x00, // interface family
2218                0x00, // padding
2219                0x00, 0x00, // link layer type
2220                0x00, 0x00, 0x00, 0x00, // link index
2221                0x00, 0x00, 0x00, 0x00, // flags
2222                0x00, 0x00, 0x00, 0x00, // flags change mask
2223                    // NLA
2224                    0x10, 0x00, // length = 16
2225                    0x03, 0x00, // type = IFLA_IFNAME
2226                    0x76, 0x65, 0x74, 0x68, 0x63, 0x30, 0x65, 0x36, 0x30, 0x64, 0x36, 0x00,
2227                    // NLA
2228                    0x08, 0x00, // length = 8
2229                    0x0d, 0x00, // type = IFLA_TXQLEN
2230                    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,                         // length
2256            0x04, 0x00,                         // IFLA_INFO_PORT_KIND
2257            0x62, 0x6f, 0x6e, 0x64, 0x00,       // V = "bond\0"
2258            0x00, 0x00, 0x00,                   // padding
2259
2260            0x14, 0x00,                 // length = 20
2261            0x05, 0x00,                 // IFLA_INFO_PORT_DATA
2262                0x06, 0x00,             // length
2263                0x05, 0x00,             // IFLA_BOND_PORT_QUEUE_ID
2264                0x00, 0x00,             // 0
2265                0x00, 0x00,             // padding
2266
2267                0x08, 0x00,             // length
2268                0x09, 0x00,             // IFLA_BOND_PORT_PRIO
2269                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,                // length
2285            0x01, 0x00,                // IFLA_INFO_KIND
2286            0x62, 0x6f, 0x6e, 0x64,    // "bond"
2287
2288            0x80, 0x00,                // length
2289            0x02, 0x00,                // IFLA_INFO_DATA
2290                0x05, 0x00,            // length
2291                0x01, 0x00,            // IFLA_BOND_MODE
2292                0x04,                  // 4 (802.3ad)
2293                0x00, 0x00, 0x00,      // padding
2294
2295                0x08, 0x00,             // length
2296                0x03, 0x00,             // IFLA_BOND_MIIMON
2297                0x32, 0x00, 0x00, 0x00, // 50
2298
2299                0x08, 0x00,             // length
2300                0x04, 0x00,             // IFLA_BOND_UPDELAY
2301                0x64, 0x00, 0x00, 0x00, // 100
2302
2303                0x08, 0x00,             // length
2304                0x05, 0x00,             // IFLA_BOND_DOWNDELAY
2305                0x64, 0x00, 0x00, 0x00, // 100
2306
2307                0x14, 0x00,             // length
2308                0x08, 0x00,             // IFLA_BOND_ARP_IP_TARGET
2309                    0x08, 0x00,              // length
2310                    0x00, 0x00,              // entry #0
2311                    0x01, 0x02, 0x03, 0x04,  // 1.2.3.4
2312                    0x08, 0x00,              // length
2313                    0x01, 0x00,              // entry #1
2314                    0x09, 0x09, 0x09, 0x09,  // 9.9.9.9
2315
2316                0x18, 0x00,             // length
2317                0x1f, 0x00,             // IFLA_BOND_NS_IP6_TARGET
2318                    0x14, 0x00,              // length
2319                    0x00, 0x00,              // entry #0
2320                    0xfd, 0x01, 0x00, 0x00,  // fd01::1
2321                    0x00, 0x00, 0x00, 0x00,
2322                    0x00, 0x00, 0x00, 0x00,
2323                    0x00, 0x00, 0x00, 0x01,
2324
2325                0x08, 0x00,             // length
2326                0x1c, 0x00,             // IFLA_BOND_PEER_NOTIF_DELAY
2327                0xc8, 0x00, 0x00, 0x00, // 200
2328
2329                0x08, 0x00,             // length
2330                0x12, 0x00,             // IFLA_BOND_MIN_LINKS
2331                0x03, 0x00, 0x00, 0x00, // 3
2332
2333                0x20, 0x00,             // length
2334                0x17, 0x00,             // IFLA_BOND_AD_INFO
2335                    0x06, 0x00,             // length
2336                    0x01, 0x00,             // IFLA_BOND_AD_INFO_AGGREGATOR
2337                    0x10, 0x00,             // 16
2338                    0x00, 0x00,             // padding
2339                    0x06, 0x00,             // length
2340                    0x02, 0x00,             // IFLA_BOND_AD_INFO_NUM_PORTS
2341                    0x02, 0x00,             // 2
2342                    0x00, 0x00,             // padding
2343                    0x0a, 0x00,             // length
2344                    0x05, 0x00,             // IFLA_BOND_AD_INFO_PARTNER_MAC
2345                    0x00, 0x11, 0x22,       // 00:11:22:33:44:55
2346                    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, // length = 11
2372        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2373        0x69, 0x70, 0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "ipvlan\0"
2374        0x00, // padding
2375
2376        0x14, 0x00, // length = 20
2377        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2378            0x06, 0x00, // length = 6
2379            0x01, 0x00, // type = 1 = IFLA_IPVLAN_MODE
2380            0x01, 0x00, // l3
2381            0x00, 0x00, // padding
2382
2383            0x06, 0x00, // length = 6
2384            0x02, 0x00, // type = 2 = IFLA_IPVLAN_FLAGS
2385            0x02, 0x00, // vepa flag
2386            0x00, 0x00, // padding
2387    ];
2388
2389    lazy_static! {
2390        static ref IPVLAN_INFO: Vec<InfoIpVlan> = vec![
2391            InfoIpVlan::Mode(1), // L3
2392            InfoIpVlan::Flags(2), // vepa flag
2393        ];
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, // length = 12
2424        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2425        0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "macvlan\0"
2426        0x0c, 0x00, // length = 12
2427        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2428            0x08, 0x00, // length = 8
2429            0x01, 0x00, // type = IFLA_MACVLAN_MODE
2430            0x04, 0x00, 0x00, 0x00, // V = 4 = bridge
2431    ];
2432
2433    lazy_static! {
2434        static ref MACVLAN_INFO: Vec<InfoMacVlan> = vec![
2435            InfoMacVlan::Mode(4), // bridge
2436        ];
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, // length = 12
2467        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2468        0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "macvlan\0"
2469        0x24, 0x00, // length = 36
2470        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2471            0x08, 0x00, // length = 8
2472            0x01, 0x00, // type = IFLA_MACVLAN_MODE
2473            0x02, 0x00, 0x00, 0x00, // V = 2 = vepa
2474
2475            0x08, 0x00, // length = 8
2476            0x07, 0x00, // type = IFLA_MACVLAN_BC_QUEUE_LEN
2477            0xe8, 0x03, 0x00, 0x00, // value 1000
2478
2479            0x08, 0x00, // length = 8
2480            0x08, 0x00, // type = IFLA_MACVLAN_BC_QUEUE_LEN_USED
2481            0xe8, 0x03, 0x00, 0x00, // value 1000
2482
2483            0x08, 0x00, // length = 8
2484            0x09, 0x00, // type = IFLA_MACVLAN_BC_CUTOFF
2485            0xff, 0xff, 0xff, 0xff, // value = -1 (signed two's complement)
2486    ];
2487
2488    lazy_static! {
2489        static ref MACVLAN_INFO_BC: Vec<InfoMacVlan> = vec![
2490            InfoMacVlan::Mode(2), // vepa
2491            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), // ifid
2525        ];
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, // length = 12
2550        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2551        0x6d, 0x61, 0x63, 0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "macvlan\0"
2552        0x48, 0x00, // length = 72
2553        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2554            0x08, 0x00, // length = 8
2555            0x03, 0x00, // type = 3 = IFLA_MACVLAN_MACADDR_MODE
2556            0x03, 0x00, 0x00, 0x00, // V = 3 = set
2557
2558            0x34, 0x00, // length = 52
2559            0x05, 0x00, // type = 5 = IFLA_MACVLAN_MACADDR_DATA
2560                0x0a, 0x00, // length = 10
2561                0x04, 0x00, // type = 4 = IFLA_MACVLAN_MACADDR
2562                0x22, 0xf5, 0x54, 0x09, 0x88, 0xd7, // V = mac address
2563                0x00, 0x00, // padding
2564
2565                0x0a, 0x00, // length = 10
2566                0x04, 0x00, // type = 4 = IFLA_MACVLAN_MACADDR
2567                0x22, 0xf5, 0x54, 0x09, 0x99, 0x32, // V = mac address
2568                0x00, 0x00, // padding
2569
2570                0x0a, 0x00, // length = 10
2571                0x04, 0x00, // type = 4 = IFLA_MACVLAN_MACADDR
2572                0x22, 0xf5, 0x54, 0x09, 0x87, 0x45, // V = mac address
2573                0x00, 0x00, // padding
2574
2575                0x0a, 0x00, // length = 10
2576                0x04, 0x00, // type = 4 = IFLA_MACVLAN_MACADDR
2577                0x22, 0xf5, 0x54, 0x09, 0x11, 0x45, // V = mac address
2578                0x00, 0x00, // padding
2579            0x08, 0x00, // length = 8
2580            0x01, 0x00, // Type = 1 = IFLA_MACVLAN_MODE
2581            0x10, 0x00, 0x00, 0x00, // V = 16 = source
2582    ];
2583
2584    lazy_static! {
2585        static ref MACVLAN_SOURCE_SET_INFO: Vec<InfoMacVlan> = vec![
2586            InfoMacVlan::MacAddrMode(3), // set
2587            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), // source
2594        ];
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, // length = 9
2658        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2659            0x76, 0x6c, 0x61, 0x6e, 0x00, // V = "vlan\0"
2660            0x00, 0x00, 0x00, // padding
2661        0x38, 0x00, // length = 56
2662        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2663            0x06, 0x00, // length - 6
2664            0x01, 0x00, // type = 1 = IFLA_VLAN_ID
2665                0x4b, 0x00, // id = 0x4b = 75
2666                0x00, 0x00, // padding
2667            0x10, 0x00, // length = 16
2668            0x03, 0x00, // type = 3 = IFLA_VLAN_EGRESS_QOS_MAPPING
2669                0x0c, 0x00, // length = 12
2670                0x01, 0x00, // type = 1 = IFLA_VLAN_QOS_MAPPING
2671                    0x03, 0x00, 0x00, 0x00, // from = 3
2672                    0x04, 0x00, 0x00, 0x00, // to = 4
2673            0x1c, 0x00, // length = 44
2674            0x04, 0x00, // type = 4 = IFLA_VLAN_INGRESS_QOS_MAPPING
2675                0x0c, 0x00, // length = 12
2676                0x01, 0x00, // type = 1 = IFLA_VLAN_QOS_MAPPING
2677                    0x00, 0x00, 0x00, 0x00, // from = 0
2678                    0x01, 0x00, 0x00, 0x00, // to = 1
2679                0x0c, 0x00, // length = 12
2680                0x01, 0x00, // type = 1 = IFLA_VLAN_QOS_MAPPING
2681                    0x01, 0x00, 0x00, 0x00, // from = 1
2682                    0x02, 0x00, 0x00, 0x00, // to = 2
2683    ];
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, // length = 10
2727        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2728            0x76, 0x78, 0x6C, 0x61, 0x6E, // V = "vxlan\0"
2729            0x00, 0x00, 0x00, // padding
2730        0x14, 0x00, // length = 20
2731        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2732            0x08, 0x00, // length - 8
2733            0x01, 0x00, // type = 1 = IFLA_VXLAN_ID
2734                0x0A, 0x00, // id = 0x0A = 10
2735                0x00, 0x00, // padding
2736        0x06, 0x00, // length = 6
2737        0x0F, 0x00, // type = 15 = IFLA_VXLAN_PORT
2738            0x12, 0xB5, // port = 4789
2739            0x00, 0x00 // padding
2740    ];
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, // length = 10
2780        0x01, 0x00, // type = 1 = IFLA_INFO_KIND
2781            0x76, 0x78, 0x6C, 0x61, 0x6E, // V = "vxlan\0"
2782            0x00, 0x00, 0x00, // padding
2783        0x14, 0x00, // length = 20
2784        0x02, 0x00, // type = 2 = IFLA_INFO_DATA
2785            0x08, 0x00, // length - 8
2786            0x01, 0x00, // type = 1 = IFLA_VXLAN_ID
2787                0x0A, 0x00, // id = 0x0A = 10
2788                0x00, 0x00, // padding
2789            0x08, 0x00, // length = 6
2790            0x0A, 0x00, // type = 10 = IFLA_VXLAN_PORT_RANGE
2791                0x23, 0x28, // min port: 9000
2792                0x23, 0x5a  // max port: 9050
2793    ];
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, // L = 11
2823        0x01, 0x00, // T = 1 (IFLA_INFO_KIND)
2824        0x6d, 0x61, 0x63, 0x73, 0x65, 0x63, 0x00, // V = "macsec"
2825        0x00, // padding
2826
2827        0x6c, 0x00, // L = 108
2828        0x02, 0x00, // T = 2 (IFLA_INFO_DATA)
2829
2830        0x0c, 0x00, // L = 16
2831        0x01, 0x00, // T = 1 (IFLA_MACSEC_SCI)
2832        0x76, 0x83, 0x22, 0x9e, 0xd6, 0xfd, 0x00, 0x0b, // V = 792912632635097974
2833
2834        0x05, 0x00, // L = 5
2835        0x03, 0x00, // T = 3 (IFLA_MACSEC_ICV_LEN)
2836        0x10, // V = 16
2837        0x00, 0x00, 0x00, // padding
2838
2839        0x0c, 0x00, // L = 16
2840        0x04, 0x00, // T = 4 (IFLA_MACSEC_CIPHER_SUITE)
2841        0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x80, 0x00, // V = MACSEC_DEFAULT_CIPHER_ID
2842
2843        0x05, 0x00, // L = 5
2844        0x06, 0x00, // T = 6 (IFLA_MACSEC_ENCODING_SA)
2845        0x00, // V = 0
2846        0x00, 0x00, 0x00, // padding
2847
2848        0x05, 0x00, // L = 5
2849        0x07, 0x00, // T = 7 (IFLA_MACSEC_ENCRYPT)
2850        0x01, // V = 1
2851        0x00, 0x00, 0x00, // padding
2852
2853        0x05, 0x00, // L = 5
2854        0x08, 0x00, // T = 8 (IFLA_MACSEC_PROTECT)
2855        0x01, // V = 1
2856        0x00, 0x00, 0x00, // padding
2857
2858        0x05, 0x00, // L = 5
2859        0x09, 0x00, // T = 9 (IFLA_MACSEC_INC_SCI)
2860        0x01, // V = 1
2861        0x00, 0x00, 0x00, // padding
2862
2863        0x05, 0x00, // L = 5
2864        0x0a, 0x00, // T = 10 (IFLA_MACSEC_ES)
2865        0x00, // V = 0
2866        0x00, 0x00, 0x00, // padding
2867
2868        0x05, 0x00, // L = 5
2869        0x0b, 0x00, // T = 11 (IFLA_MACSEC_SCB)
2870        0x00, // V = 0
2871        0x00, 0x00, 0x00, // padding
2872
2873        0x05, 0x00, // L = 5
2874        0x0c, 0x00, // T = 12 (IFLA_MACSEC_REPLAY_PROTECT)
2875        0x00, // V = 0
2876        0x00, 0x00, 0x00, // padding
2877
2878        0x05, 0x00, // L = 5
2879        0x0d, 0x00, // T = 13 (IFLA_MACSEC_VALIDATION)
2880        0x02, // V = 2 (MACSEC_VALIDATE_STRICT)
2881        0x00, 0x00, 0x00, // padding
2882
2883        0x05, 0x00, // L = 5
2884        0x0f, 0x00, // T = 15 (IFLA_MACSEC_OFFLOAD)
2885        0x00, // V = 0 (MACSEC_OFFLOAD_OFF)
2886        0x00, 0x00, 0x00 // padding
2887    ];
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}