netlink_packet_route/route/
mpls.rs

1// SPDX-License-Identifier: MIT
2
3use super::error::RouteError;
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
5use netlink_packet_utils::parsers::parse_u8;
6use netlink_packet_utils::traits::{Emitable, Parseable};
7
8const MPLS_IPTUNNEL_DST: u16 = 1;
9const MPLS_IPTUNNEL_TTL: u16 = 2;
10
11/// Netlink attributes for `RTA_ENCAP` with `RTA_ENCAP_TYPE` set to
12/// `LWTUNNEL_ENCAP_MPLS`.
13#[derive(Debug, PartialEq, Eq, Clone)]
14#[non_exhaustive]
15pub enum RouteMplsIpTunnel {
16    Destination(Vec<MplsLabel>),
17    Ttl(u8),
18    Other(DefaultNla),
19}
20
21impl Nla for RouteMplsIpTunnel {
22    fn value_len(&self) -> usize {
23        match self {
24            Self::Destination(v) => VecMplsLabel(v.to_vec()).buffer_len(),
25            Self::Ttl(_) => 1,
26            Self::Other(attr) => attr.value_len(),
27        }
28    }
29
30    fn kind(&self) -> u16 {
31        match self {
32            Self::Destination(_) => MPLS_IPTUNNEL_DST,
33            Self::Ttl(_) => MPLS_IPTUNNEL_TTL,
34            Self::Other(attr) => attr.kind(),
35        }
36    }
37
38    fn emit_value(&self, buffer: &mut [u8]) {
39        match self {
40            Self::Destination(v) => VecMplsLabel(v.to_vec()).emit(buffer),
41            Self::Ttl(ttl) => buffer[0] = *ttl,
42            Self::Other(attr) => attr.emit_value(buffer),
43        }
44    }
45}
46
47impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for RouteMplsIpTunnel {
48    type Error = RouteError;
49    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, RouteError> {
50        let payload = buf.value();
51        Ok(match buf.kind() {
52            MPLS_IPTUNNEL_DST => Self::Destination(VecMplsLabel::parse(payload)?.0),
53            MPLS_IPTUNNEL_TTL => {
54                Self::Ttl(parse_u8(payload).map_err(RouteError::InvalidMplsIpTunnelTtl)?)
55            }
56            _ => Self::Other(DefaultNla::parse(buf).map_err(RouteError::InvalidMplsIpTunnelTtl)?),
57        })
58    }
59}
60
61const MPLS_LS_LABEL_MASK: u32 = 0xFFFFF000;
62const MPLS_LS_LABEL_SHIFT: u32 = 12;
63const MPLS_LS_TC_MASK: u32 = 0x00000E00;
64const MPLS_LS_TC_SHIFT: u32 = 9;
65const MPLS_LS_S_MASK: u32 = 0x00000100;
66const MPLS_LS_S_SHIFT: u32 = 8;
67const MPLS_LS_TTL_MASK: u32 = 0x000000FF;
68const MPLS_LS_TTL_SHIFT: u32 = 0;
69
70#[derive(Debug, PartialEq, Eq, Clone, Copy)]
71/// MPLS label defined in RFC 3032 and updated by RFC 5462
72pub struct MplsLabel {
73    /// label, 20 bytes
74    pub label: u32,
75    /// Traffic Class, 3 bits
76    pub traffic_class: u8,
77    /// Bottom of Stack, 1 bit
78    pub bottom_of_stack: bool,
79    /// Time to Live
80    pub ttl: u8,
81}
82
83impl MplsLabel {
84    pub(crate) fn parse(payload: &[u8]) -> Result<Self, RouteError> {
85        if payload.len() == 4 {
86            Ok(Self::from(u32::from_be_bytes([payload[0], payload[1], payload[2], payload[3]])))
87        } else {
88            Err(RouteError::ParseMplsLabel { expected: 4, got: payload.len() })
89        }
90    }
91}
92
93impl Emitable for MplsLabel {
94    fn buffer_len(&self) -> usize {
95        4
96    }
97
98    fn emit(&self, buffer: &mut [u8]) {
99        buffer.copy_from_slice(u32::from(*self).to_be_bytes().as_slice())
100    }
101}
102
103impl From<u32> for MplsLabel {
104    fn from(d: u32) -> Self {
105        let label = (d & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
106        let traffic_class = ((d & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT) as u8;
107        let bottom_of_stack = (d & MPLS_LS_S_MASK) > 0;
108        let ttl = (d & MPLS_LS_TTL_MASK) as u8;
109        Self { label, traffic_class, bottom_of_stack, ttl }
110    }
111}
112
113impl From<MplsLabel> for u32 {
114    fn from(v: MplsLabel) -> u32 {
115        v.label << MPLS_LS_LABEL_SHIFT
116            | (v.traffic_class as u32) << MPLS_LS_TC_SHIFT
117            | (v.bottom_of_stack as u32) << MPLS_LS_S_SHIFT
118            | (v.ttl as u32) << MPLS_LS_TTL_SHIFT
119    }
120}
121
122pub(crate) struct VecMplsLabel(pub(crate) Vec<MplsLabel>);
123
124impl VecMplsLabel {
125    pub(crate) fn parse(payload: &[u8]) -> Result<Self, RouteError> {
126        let mut labels = vec![];
127        let mut i: usize = 0;
128        while i + 4 <= payload.len() {
129            labels.push(MplsLabel::parse(&payload[i..i + 4])?);
130            i += 4;
131        }
132        Ok(Self(labels))
133    }
134}
135
136impl Emitable for VecMplsLabel {
137    fn buffer_len(&self) -> usize {
138        self.0.len() * 4
139    }
140
141    fn emit(&self, buffer: &mut [u8]) {
142        for (i, label) in self.0.iter().enumerate() {
143            label.emit(&mut buffer[i * 4..i * 4 + 4]);
144        }
145    }
146}
147
148const MPLS_TTL_PROP_DEFAULT: u8 = 0;
149const MPLS_TTL_PROP_ENABLED: u8 = 1;
150const MPLS_TTL_PROP_DISABLED: u8 = 2;
151
152#[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
153#[non_exhaustive]
154pub enum RouteMplsTtlPropagation {
155    #[default]
156    Default,
157    Enabled,
158    Disabled,
159    Other(u8),
160}
161
162impl From<u8> for RouteMplsTtlPropagation {
163    fn from(d: u8) -> Self {
164        match d {
165            MPLS_TTL_PROP_DEFAULT => Self::Default,
166            MPLS_TTL_PROP_ENABLED => Self::Enabled,
167            MPLS_TTL_PROP_DISABLED => Self::Disabled,
168            _ => Self::Other(d),
169        }
170    }
171}
172
173impl From<RouteMplsTtlPropagation> for u8 {
174    fn from(v: RouteMplsTtlPropagation) -> u8 {
175        match v {
176            RouteMplsTtlPropagation::Default => MPLS_TTL_PROP_DEFAULT,
177            RouteMplsTtlPropagation::Enabled => MPLS_TTL_PROP_ENABLED,
178            RouteMplsTtlPropagation::Disabled => MPLS_TTL_PROP_DISABLED,
179            RouteMplsTtlPropagation::Other(d) => d,
180        }
181    }
182}