netlink_packet_route/rtnl/route/nlas/
mpls_ip_tunnel.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::{
5    nla::{DefaultNla, Nla, NlaBuffer},
6    parsers::parse_u8,
7    traits::Parseable,
8    DecodeError,
9};
10
11use crate::constants::*;
12
13/// Netlink attributes for `RTA_ENCAP` with `RTA_ENCAP_TYPE` set to
14/// `LWTUNNEL_ENCAP_MPLS`.
15#[non_exhaustive]
16pub enum MplsIpTunnel {
17    Destination(Vec<u8>),
18    Ttl(u8),
19    Other(DefaultNla),
20}
21
22impl Nla for MplsIpTunnel {
23    fn value_len(&self) -> usize {
24        use self::MplsIpTunnel::*;
25        match self {
26            Destination(bytes) => bytes.len(),
27            Ttl(_) => 1,
28            Other(attr) => attr.value_len(),
29        }
30    }
31
32    fn kind(&self) -> u16 {
33        use self::MplsIpTunnel::*;
34        match self {
35            Destination(_) => MPLS_IPTUNNEL_DST,
36            Ttl(_) => MPLS_IPTUNNEL_TTL,
37            Other(attr) => attr.kind(),
38        }
39    }
40
41    fn emit_value(&self, buffer: &mut [u8]) {
42        use self::MplsIpTunnel::*;
43        match self {
44            Destination(bytes) => buffer.copy_from_slice(bytes.as_slice()),
45            Ttl(ttl) => buffer[0] = *ttl,
46            Other(attr) => attr.emit_value(buffer),
47        }
48    }
49}
50
51impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for MplsIpTunnel {
52    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
53        use self::MplsIpTunnel::*;
54        let payload = buf.value();
55        Ok(match buf.kind() {
56            MPLS_IPTUNNEL_DST => Destination(payload.to_vec()),
57            MPLS_IPTUNNEL_TTL => {
58                Ttl(parse_u8(payload)
59                    .context("invalid MPLS_IPTUNNEL_TTL value")?)
60            }
61            _ => Other(
62                DefaultNla::parse(buf)
63                    .context("invalid NLA value (unknown type) value")?,
64            ),
65        })
66    }
67}