netlink_packet_route/rtnl/link/nlas/
link_infos.rs

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