netlink_packet_route/rtnl/route/nlas/
mpls_ip_tunnel.rs

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