netlink_packet_route/route/
mpls.rs
1use 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#[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)]
71pub struct MplsLabel {
73 pub label: u32,
75 pub traffic_class: u8,
77 pub bottom_of_stack: bool,
79 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}