netlink_packet_route/route/
lwtunnel.rs

1// SPDX-License-Identifier: MIT
2
3use super::{RouteError, RouteMplsIpTunnel};
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer, NlasIterator};
5use netlink_packet_utils::traits::{Emitable, Parseable, ParseableParametrized};
6
7const LWTUNNEL_ENCAP_NONE: u16 = 0;
8const LWTUNNEL_ENCAP_MPLS: u16 = 1;
9const LWTUNNEL_ENCAP_IP: u16 = 2;
10const LWTUNNEL_ENCAP_ILA: u16 = 3;
11const LWTUNNEL_ENCAP_IP6: u16 = 4;
12const LWTUNNEL_ENCAP_SEG6: u16 = 5;
13const LWTUNNEL_ENCAP_BPF: u16 = 6;
14const LWTUNNEL_ENCAP_SEG6_LOCAL: u16 = 7;
15const LWTUNNEL_ENCAP_RPL: u16 = 8;
16const LWTUNNEL_ENCAP_IOAM6: u16 = 9;
17const LWTUNNEL_ENCAP_XFRM: u16 = 10;
18
19#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
20#[non_exhaustive]
21pub enum RouteLwEnCapType {
22    #[default]
23    None,
24    Mpls,
25    Ip,
26    Ila,
27    Ip6,
28    Seg6,
29    Bpf,
30    Seg6Local,
31    Rpl,
32    Ioam6,
33    Xfrm,
34    Other(u16),
35}
36
37impl From<u16> for RouteLwEnCapType {
38    fn from(d: u16) -> Self {
39        match d {
40            LWTUNNEL_ENCAP_NONE => Self::None,
41            LWTUNNEL_ENCAP_MPLS => Self::Mpls,
42            LWTUNNEL_ENCAP_IP => Self::Ip,
43            LWTUNNEL_ENCAP_ILA => Self::Ila,
44            LWTUNNEL_ENCAP_IP6 => Self::Ip6,
45            LWTUNNEL_ENCAP_SEG6 => Self::Seg6,
46            LWTUNNEL_ENCAP_BPF => Self::Bpf,
47            LWTUNNEL_ENCAP_SEG6_LOCAL => Self::Seg6Local,
48            LWTUNNEL_ENCAP_RPL => Self::Rpl,
49            LWTUNNEL_ENCAP_IOAM6 => Self::Ioam6,
50            LWTUNNEL_ENCAP_XFRM => Self::Xfrm,
51            _ => Self::Other(d),
52        }
53    }
54}
55
56impl From<RouteLwEnCapType> for u16 {
57    fn from(v: RouteLwEnCapType) -> u16 {
58        match v {
59            RouteLwEnCapType::None => LWTUNNEL_ENCAP_NONE,
60            RouteLwEnCapType::Mpls => LWTUNNEL_ENCAP_MPLS,
61            RouteLwEnCapType::Ip => LWTUNNEL_ENCAP_IP,
62            RouteLwEnCapType::Ila => LWTUNNEL_ENCAP_ILA,
63            RouteLwEnCapType::Ip6 => LWTUNNEL_ENCAP_IP6,
64            RouteLwEnCapType::Seg6 => LWTUNNEL_ENCAP_SEG6,
65            RouteLwEnCapType::Bpf => LWTUNNEL_ENCAP_BPF,
66            RouteLwEnCapType::Seg6Local => LWTUNNEL_ENCAP_SEG6_LOCAL,
67            RouteLwEnCapType::Rpl => LWTUNNEL_ENCAP_RPL,
68            RouteLwEnCapType::Ioam6 => LWTUNNEL_ENCAP_IOAM6,
69            RouteLwEnCapType::Xfrm => LWTUNNEL_ENCAP_XFRM,
70            RouteLwEnCapType::Other(d) => d,
71        }
72    }
73}
74
75impl Emitable for RouteLwEnCapType {
76    fn buffer_len(&self) -> usize {
77        2
78    }
79
80    fn emit(&self, buffer: &mut [u8]) {
81        buffer.copy_from_slice(&(u16::from(*self).to_ne_bytes()))
82    }
83}
84
85impl std::fmt::Display for RouteLwEnCapType {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        match self {
88            Self::None => write!(f, "none"),
89            Self::Mpls => write!(f, "mpls"),
90            Self::Ip => write!(f, "ip"),
91            Self::Ila => write!(f, "ila"),
92            Self::Ip6 => write!(f, "ip6"),
93            Self::Seg6 => write!(f, "seg6"),
94            Self::Bpf => write!(f, "bpf"),
95            Self::Seg6Local => write!(f, "seg6_local"),
96            Self::Rpl => write!(f, "rpl"),
97            Self::Ioam6 => write!(f, "ioam6"),
98            Self::Xfrm => write!(f, "xfrm"),
99            Self::Other(d) => write!(f, "other({d})"),
100        }
101    }
102}
103
104#[derive(Debug, PartialEq, Eq, Clone)]
105#[non_exhaustive]
106pub enum RouteLwTunnelEncap {
107    Mpls(RouteMplsIpTunnel),
108    Other(DefaultNla),
109}
110
111impl Nla for RouteLwTunnelEncap {
112    fn value_len(&self) -> usize {
113        match self {
114            Self::Mpls(v) => v.value_len(),
115            Self::Other(v) => v.value_len(),
116        }
117    }
118
119    fn emit_value(&self, buffer: &mut [u8]) {
120        match self {
121            Self::Mpls(v) => v.emit_value(buffer),
122            Self::Other(v) => v.emit_value(buffer),
123        }
124    }
125
126    fn kind(&self) -> u16 {
127        match self {
128            Self::Mpls(v) => v.kind(),
129            Self::Other(v) => v.kind(),
130        }
131    }
132}
133
134impl<'a, T> ParseableParametrized<NlaBuffer<&'a T>, RouteLwEnCapType> for RouteLwTunnelEncap
135where
136    T: AsRef<[u8]> + ?Sized,
137{
138    type Error = RouteError;
139    fn parse_with_param(
140        buf: &NlaBuffer<&'a T>,
141        kind: RouteLwEnCapType,
142    ) -> Result<Self, Self::Error> {
143        Ok(match kind {
144            RouteLwEnCapType::Mpls => Self::Mpls(RouteMplsIpTunnel::parse(buf)?),
145            _ => Self::Other(DefaultNla::parse(buf)?),
146        })
147    }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone)]
151#[non_exhaustive]
152pub(crate) struct VecRouteLwTunnelEncap(pub(crate) Vec<RouteLwTunnelEncap>);
153
154impl<'a, T> ParseableParametrized<NlaBuffer<&'a T>, RouteLwEnCapType> for VecRouteLwTunnelEncap
155where
156    T: AsRef<[u8]> + ?Sized,
157{
158    type Error = RouteError;
159    fn parse_with_param(
160        buf: &NlaBuffer<&'a T>,
161        kind: RouteLwEnCapType,
162    ) -> Result<Self, RouteError> {
163        let mut ret = Vec::new();
164        for nla in NlasIterator::new(buf.value()) {
165            let nla = nla.map_err(|error| RouteError::InvalidRtaEncap { error, kind })?;
166            ret.push(RouteLwTunnelEncap::parse_with_param(&nla, kind)?);
167        }
168        Ok(Self(ret))
169    }
170}