netlink_packet_route/link/link_info/
vxlan.rs
1use anyhow::Context;
4use byteorder::{BigEndian, ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::{parse_u16_be, parse_u32, parse_u8};
7use netlink_packet_utils::traits::Parseable;
8use netlink_packet_utils::DecodeError;
9
10const IFLA_VXLAN_ID: u16 = 1;
11const IFLA_VXLAN_GROUP: u16 = 2;
12const IFLA_VXLAN_LINK: u16 = 3;
13const IFLA_VXLAN_LOCAL: u16 = 4;
14const IFLA_VXLAN_TTL: u16 = 5;
15const IFLA_VXLAN_TOS: u16 = 6;
16const IFLA_VXLAN_LEARNING: u16 = 7;
17const IFLA_VXLAN_AGEING: u16 = 8;
18const IFLA_VXLAN_LIMIT: u16 = 9;
19const IFLA_VXLAN_PORT_RANGE: u16 = 10;
20const IFLA_VXLAN_PROXY: u16 = 11;
21const IFLA_VXLAN_RSC: u16 = 12;
22const IFLA_VXLAN_L2MISS: u16 = 13;
23const IFLA_VXLAN_L3MISS: u16 = 14;
24const IFLA_VXLAN_PORT: u16 = 15;
25const IFLA_VXLAN_GROUP6: u16 = 16;
26const IFLA_VXLAN_LOCAL6: u16 = 17;
27const IFLA_VXLAN_UDP_CSUM: u16 = 18;
28const IFLA_VXLAN_UDP_ZERO_CSUM6_TX: u16 = 19;
29const IFLA_VXLAN_UDP_ZERO_CSUM6_RX: u16 = 20;
30const IFLA_VXLAN_REMCSUM_TX: u16 = 21;
31const IFLA_VXLAN_REMCSUM_RX: u16 = 22;
32const IFLA_VXLAN_GBP: u16 = 23;
33const IFLA_VXLAN_REMCSUM_NOPARTIAL: u16 = 24;
34const IFLA_VXLAN_COLLECT_METADATA: u16 = 25;
35const IFLA_VXLAN_LABEL: u16 = 26;
36const IFLA_VXLAN_GPE: u16 = 27;
37const IFLA_VXLAN_TTL_INHERIT: u16 = 28;
38const IFLA_VXLAN_DF: u16 = 29;
39const IFLA_VXLAN_VNIFILTER: u16 = 30;
40const IFLA_VXLAN_LOCALBYPASS: u16 = 31;
41
42#[derive(Debug, PartialEq, Eq, Clone)]
43#[non_exhaustive]
44pub enum InfoVxlan {
45 Id(u32),
46 Group(Vec<u8>),
47 Group6(Vec<u8>),
48 Link(u32),
49 Local(Vec<u8>),
50 Local6(Vec<u8>),
51 Tos(u8),
52 Ttl(u8),
53 Label(u32),
54 Learning(bool),
55 Ageing(u32),
56 Limit(u32),
57 PortRange((u16, u16)),
58 Proxy(bool),
59 Rsc(bool),
60 L2Miss(bool),
61 L3Miss(bool),
62 CollectMetadata(bool),
63 Port(u16),
64 UDPCsum(bool),
65 UDPZeroCsumTX(bool),
66 UDPZeroCsumRX(bool),
67 RemCsumTX(bool),
68 RemCsumRX(bool),
69 Gbp(bool),
70 Gpe(bool),
71 RemCsumNoPartial(bool),
72 TtlInherit(bool),
73 Df(u8),
74 Vnifilter(bool),
75 Localbypass(bool),
76 Other(DefaultNla),
77}
78
79impl Nla for InfoVxlan {
80 fn value_len(&self) -> usize {
81 match self {
82 Self::Tos(_)
83 | Self::Ttl(_)
84 | Self::Learning(_)
85 | Self::Proxy(_)
86 | Self::Rsc(_)
87 | Self::L2Miss(_)
88 | Self::L3Miss(_)
89 | Self::CollectMetadata(_)
90 | Self::UDPCsum(_)
91 | Self::UDPZeroCsumTX(_)
92 | Self::UDPZeroCsumRX(_)
93 | Self::RemCsumTX(_)
94 | Self::RemCsumRX(_)
95 | Self::TtlInherit(_)
96 | Self::Df(_)
97 | Self::Vnifilter(_)
98 | Self::Localbypass(_) => 1,
99 Self::Gbp(_) | Self::Gpe(_) | Self::RemCsumNoPartial(_) => 0,
100 Self::Port(_) => 2,
101 Self::Id(_)
102 | Self::Label(_)
103 | Self::Link(_)
104 | Self::Ageing(_)
105 | Self::Limit(_)
106 | Self::PortRange(_) => 4,
107 Self::Local(bytes) | Self::Local6(bytes) | Self::Group(bytes) | Self::Group6(bytes) => {
108 bytes.len()
109 }
110 Self::Other(nla) => nla.value_len(),
111 }
112 }
113
114 fn emit_value(&self, buffer: &mut [u8]) {
115 match self {
116 Self::Id(value)
117 | Self::Label(value)
118 | Self::Link(value)
119 | Self::Ageing(value)
120 | Self::Limit(value) => NativeEndian::write_u32(buffer, *value),
121 Self::Gbp(_value) | Self::Gpe(_value) | Self::RemCsumNoPartial(_value) => (),
122 Self::Tos(value) | Self::Ttl(value) | Self::Df(value) => buffer[0] = *value,
123 Self::Vnifilter(value)
124 | Self::Localbypass(value)
125 | Self::Learning(value)
126 | Self::Proxy(value)
127 | Self::Rsc(value)
128 | Self::L2Miss(value)
129 | Self::L3Miss(value)
130 | Self::CollectMetadata(value)
131 | Self::UDPCsum(value)
132 | Self::UDPZeroCsumTX(value)
133 | Self::UDPZeroCsumRX(value)
134 | Self::RemCsumTX(value)
135 | Self::RemCsumRX(value)
136 | Self::TtlInherit(value) => buffer[0] = *value as u8,
137 Self::Local(value) | Self::Group(value) | Self::Group6(value) | Self::Local6(value) => {
138 buffer.copy_from_slice(value.as_slice())
139 }
140 Self::Port(value) => BigEndian::write_u16(buffer, *value),
141 Self::PortRange(range) => {
142 BigEndian::write_u16(buffer, range.0);
143 BigEndian::write_u16(&mut buffer[2..], range.1)
144 }
145 Self::Other(nla) => nla.emit_value(buffer),
146 }
147 }
148
149 fn kind(&self) -> u16 {
150 match self {
151 Self::Id(_) => IFLA_VXLAN_ID,
152 Self::Group(_) => IFLA_VXLAN_GROUP,
153 Self::Group6(_) => IFLA_VXLAN_GROUP6,
154 Self::Link(_) => IFLA_VXLAN_LINK,
155 Self::Local(_) => IFLA_VXLAN_LOCAL,
156 Self::Local6(_) => IFLA_VXLAN_LOCAL6,
157 Self::Tos(_) => IFLA_VXLAN_TOS,
158 Self::Ttl(_) => IFLA_VXLAN_TTL,
159 Self::Label(_) => IFLA_VXLAN_LABEL,
160 Self::Learning(_) => IFLA_VXLAN_LEARNING,
161 Self::Ageing(_) => IFLA_VXLAN_AGEING,
162 Self::Limit(_) => IFLA_VXLAN_LIMIT,
163 Self::PortRange(_) => IFLA_VXLAN_PORT_RANGE,
164 Self::Proxy(_) => IFLA_VXLAN_PROXY,
165 Self::Rsc(_) => IFLA_VXLAN_RSC,
166 Self::L2Miss(_) => IFLA_VXLAN_L2MISS,
167 Self::L3Miss(_) => IFLA_VXLAN_L3MISS,
168 Self::CollectMetadata(_) => IFLA_VXLAN_COLLECT_METADATA,
169 Self::Port(_) => IFLA_VXLAN_PORT,
170 Self::UDPCsum(_) => IFLA_VXLAN_UDP_CSUM,
171 Self::UDPZeroCsumTX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
172 Self::UDPZeroCsumRX(_) => IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
173 Self::RemCsumTX(_) => IFLA_VXLAN_REMCSUM_TX,
174 Self::RemCsumRX(_) => IFLA_VXLAN_REMCSUM_RX,
175 Self::Gbp(_) => IFLA_VXLAN_GBP,
176 Self::Gpe(_) => IFLA_VXLAN_GPE,
177 Self::RemCsumNoPartial(_) => IFLA_VXLAN_REMCSUM_NOPARTIAL,
178 Self::TtlInherit(_) => IFLA_VXLAN_TTL_INHERIT,
179 Self::Df(_) => IFLA_VXLAN_DF,
180 Self::Vnifilter(_) => IFLA_VXLAN_VNIFILTER,
181 Self::Localbypass(_) => IFLA_VXLAN_LOCALBYPASS,
182 Self::Other(nla) => nla.kind(),
183 }
184 }
185}
186
187impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoVxlan {
188 type Error = DecodeError;
189 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
190 let payload = buf.value();
191 Ok(match buf.kind() {
192 IFLA_VXLAN_ID => Self::Id(parse_u32(payload).context("invalid IFLA_VXLAN_ID value")?),
193 IFLA_VXLAN_GROUP => Self::Group(payload.to_vec()),
194 IFLA_VXLAN_GROUP6 => Self::Group6(payload.to_vec()),
195 IFLA_VXLAN_LINK => {
196 Self::Link(parse_u32(payload).context("invalid IFLA_VXLAN_LINK value")?)
197 }
198 IFLA_VXLAN_LOCAL => Self::Local(payload.to_vec()),
199 IFLA_VXLAN_LOCAL6 => Self::Local6(payload.to_vec()),
200 IFLA_VXLAN_TOS => Self::Tos(parse_u8(payload).context("invalid IFLA_VXLAN_TOS value")?),
201 IFLA_VXLAN_TTL => Self::Ttl(parse_u8(payload).context("invalid IFLA_VXLAN_TTL value")?),
202 IFLA_VXLAN_LABEL => {
203 Self::Label(parse_u32(payload).context("invalid IFLA_VXLAN_LABEL value")?)
204 }
205 IFLA_VXLAN_LEARNING => {
206 Self::Learning(parse_u8(payload).context("invalid IFLA_VXLAN_LEARNING value")? > 0)
207 }
208 IFLA_VXLAN_AGEING => {
209 Self::Ageing(parse_u32(payload).context("invalid IFLA_VXLAN_AGEING value")?)
210 }
211 IFLA_VXLAN_LIMIT => {
212 Self::Limit(parse_u32(payload).context("invalid IFLA_VXLAN_LIMIT value")?)
213 }
214 IFLA_VXLAN_PROXY => {
215 Self::Proxy(parse_u8(payload).context("invalid IFLA_VXLAN_PROXY value")? > 0)
216 }
217 IFLA_VXLAN_RSC => {
218 Self::Rsc(parse_u8(payload).context("invalid IFLA_VXLAN_RSC value")? > 0)
219 }
220 IFLA_VXLAN_L2MISS => {
221 Self::L2Miss(parse_u8(payload).context("invalid IFLA_VXLAN_L2MISS value")? > 0)
222 }
223 IFLA_VXLAN_L3MISS => {
224 Self::L3Miss(parse_u8(payload).context("invalid IFLA_VXLAN_L3MISS value")? > 0)
225 }
226 IFLA_VXLAN_COLLECT_METADATA => Self::CollectMetadata(
227 parse_u8(payload).context("invalid IFLA_VXLAN_COLLECT_METADATA value")? > 0,
228 ),
229 IFLA_VXLAN_PORT_RANGE => {
230 let err = "invalid IFLA_VXLAN_PORT value";
231 if payload.len() != 4 {
232 return Err(err.into());
233 }
234 let low = parse_u16_be(&payload[0..2]).context(err)?;
235 let high = parse_u16_be(&payload[2..]).context(err)?;
236 Self::PortRange((low, high))
237 }
238 IFLA_VXLAN_PORT => {
239 Self::Port(parse_u16_be(payload).context("invalid IFLA_VXLAN_PORT value")?)
240 }
241 IFLA_VXLAN_UDP_CSUM => {
242 Self::UDPCsum(parse_u8(payload).context("invalid IFLA_VXLAN_UDP_CSUM value")? > 0)
243 }
244 IFLA_VXLAN_UDP_ZERO_CSUM6_TX => Self::UDPZeroCsumTX(
245 parse_u8(payload).context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_TX value")? > 0,
246 ),
247 IFLA_VXLAN_UDP_ZERO_CSUM6_RX => Self::UDPZeroCsumRX(
248 parse_u8(payload).context("invalid IFLA_VXLAN_UDP_ZERO_CSUM6_RX value")? > 0,
249 ),
250 IFLA_VXLAN_REMCSUM_TX => Self::RemCsumTX(
251 parse_u8(payload).context("invalid IFLA_VXLAN_REMCSUM_TX value")? > 0,
252 ),
253 IFLA_VXLAN_REMCSUM_RX => Self::RemCsumRX(
254 parse_u8(payload).context("invalid IFLA_VXLAN_REMCSUM_RX value")? > 0,
255 ),
256 IFLA_VXLAN_DF => Self::Df(parse_u8(payload).context("invalid IFLA_VXLAN_DF value")?),
257 IFLA_VXLAN_GBP => Self::Gbp(true),
258 IFLA_VXLAN_GPE => Self::Gpe(true),
259 IFLA_VXLAN_REMCSUM_NOPARTIAL => Self::RemCsumNoPartial(true),
260 IFLA_VXLAN_TTL_INHERIT => Self::TtlInherit(
261 parse_u8(payload).context("invalid IFLA_VXLAN_TTL_INHERIT value")? > 0,
262 ),
263 IFLA_VXLAN_VNIFILTER => Self::Vnifilter(
264 parse_u8(payload).context("invalid IFLA_VXLAN_VNIFILTER value")? > 0,
265 ),
266 IFLA_VXLAN_LOCALBYPASS => Self::Localbypass(
267 parse_u8(payload).context("invalid IFLA_VXLAN_LOCALBYPASS value")? > 0,
268 ),
269 unknown_kind => Self::Other(DefaultNla::parse(buf).context(format!(
270 "Failed to parse IFLA_INFO_DATA(vxlan) NLA type: {unknown_kind} as DefaultNla"
271 ))?),
272 })
273 }
274}