1use netlink_packet_core::{
4 emit_u16, emit_u32, emit_u64, parse_u16, parse_u32, parse_u64, parse_u8,
5 DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
6};
7
8use crate::link::{BridgeId, BridgeIdBuffer};
9
10const IFLA_BRPORT_STATE: u16 = 1;
11const IFLA_BRPORT_PRIORITY: u16 = 2;
12const IFLA_BRPORT_COST: u16 = 3;
13const IFLA_BRPORT_MODE: u16 = 4;
14const IFLA_BRPORT_GUARD: u16 = 5;
15const IFLA_BRPORT_PROTECT: u16 = 6;
16const IFLA_BRPORT_FAST_LEAVE: u16 = 7;
17const IFLA_BRPORT_LEARNING: u16 = 8;
18const IFLA_BRPORT_UNICAST_FLOOD: u16 = 9;
19const IFLA_BRPORT_PROXYARP: u16 = 10;
20const IFLA_BRPORT_PROXYARP_WIFI: u16 = 12;
23const IFLA_BRPORT_ROOT_ID: u16 = 13;
24const IFLA_BRPORT_BRIDGE_ID: u16 = 14;
25const IFLA_BRPORT_DESIGNATED_PORT: u16 = 15;
26const IFLA_BRPORT_DESIGNATED_COST: u16 = 16;
27const IFLA_BRPORT_ID: u16 = 17;
28const IFLA_BRPORT_NO: u16 = 18;
29const IFLA_BRPORT_TOPOLOGY_CHANGE_ACK: u16 = 19;
30const IFLA_BRPORT_CONFIG_PENDING: u16 = 20;
31const IFLA_BRPORT_MESSAGE_AGE_TIMER: u16 = 21;
32const IFLA_BRPORT_FORWARD_DELAY_TIMER: u16 = 22;
33const IFLA_BRPORT_HOLD_TIMER: u16 = 23;
34const IFLA_BRPORT_FLUSH: u16 = 24;
35const IFLA_BRPORT_MULTICAST_ROUTER: u16 = 25;
36const IFLA_BRPORT_MCAST_FLOOD: u16 = 27;
38const IFLA_BRPORT_MCAST_TO_UCAST: u16 = 28;
39const IFLA_BRPORT_VLAN_TUNNEL: u16 = 29;
40const IFLA_BRPORT_BCAST_FLOOD: u16 = 30;
41const IFLA_BRPORT_GROUP_FWD_MASK: u16 = 31;
42const IFLA_BRPORT_NEIGH_SUPPRESS: u16 = 32;
43const IFLA_BRPORT_ISOLATED: u16 = 33;
44const IFLA_BRPORT_BACKUP_PORT: u16 = 34;
45const IFLA_BRPORT_MRP_RING_OPEN: u16 = 35;
46const IFLA_BRPORT_MRP_IN_OPEN: u16 = 36;
47const IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT: u16 = 37;
48const IFLA_BRPORT_MCAST_EHT_HOSTS_CNT: u16 = 38;
49const IFLA_BRPORT_LOCKED: u16 = 39;
50const IFLA_BRPORT_MAB: u16 = 40;
51const IFLA_BRPORT_MCAST_N_GROUPS: u16 = 41;
52const IFLA_BRPORT_MCAST_MAX_GROUPS: u16 = 42;
53const IFLA_BRPORT_NEIGH_VLAN_SUPPRESS: u16 = 43;
54const IFLA_BRPORT_BACKUP_NHID: u16 = 44;
55
56#[derive(Debug, PartialEq, Eq, Clone)]
57#[non_exhaustive]
58pub enum InfoBridgePort {
59 State(BridgePortState),
60 Priority(u16),
61 Cost(u32),
62 HairpinMode(bool),
63 Guard(bool),
64 Protect(bool),
65 FastLeave(bool),
66 Learning(bool),
67 UnicastFlood(bool),
68 ProxyARP(bool),
69 ProxyARPWifi(bool),
70 RootId(BridgeId),
71 BridgeId(BridgeId),
72 DesignatedPort(u16),
73 DesignatedCost(u16),
74 PortId(u16),
75 PortNumber(u16),
76 TopologyChangeAck(bool),
77 ConfigPending(bool),
78 MessageAgeTimer(u64),
79 ForwardDelayTimer(u64),
80 HoldTimer(u64),
81 Flush,
82 MulticastRouter(BridgePortMulticastRouter),
83 MulticastFlood(bool),
84 MulticastToUnicast(bool),
85 VlanTunnel(bool),
86 BroadcastFlood(bool),
87 GroupFwdMask(u16),
88 NeighSupress(bool),
89 Isolated(bool),
90 BackupPort(u32),
91 MrpRingOpen(bool),
92 MrpInOpen(bool),
93 MulticastEhtHostsLimit(u32),
94 MulticastEhtHostsCnt(u32),
95 Locked(bool),
96 Mab(bool),
97 MulticastNGroups(u32),
98 MulticastMaxGroups(u32),
99 NeighVlanSupress(bool),
100 BackupNextHopId(u32),
101 Other(DefaultNla),
102}
103
104impl Nla for InfoBridgePort {
105 fn value_len(&self) -> usize {
106 match self {
107 InfoBridgePort::Flush => 0,
108 InfoBridgePort::State(_)
109 | InfoBridgePort::HairpinMode(_)
110 | InfoBridgePort::Guard(_)
111 | InfoBridgePort::Protect(_)
112 | InfoBridgePort::FastLeave(_)
113 | InfoBridgePort::Learning(_)
114 | InfoBridgePort::UnicastFlood(_)
115 | InfoBridgePort::ProxyARP(_)
116 | InfoBridgePort::ProxyARPWifi(_)
117 | InfoBridgePort::TopologyChangeAck(_)
118 | InfoBridgePort::ConfigPending(_)
119 | InfoBridgePort::MulticastRouter(_)
120 | InfoBridgePort::MulticastFlood(_)
121 | InfoBridgePort::MulticastToUnicast(_)
122 | InfoBridgePort::VlanTunnel(_)
123 | InfoBridgePort::BroadcastFlood(_)
124 | InfoBridgePort::NeighSupress(_)
125 | InfoBridgePort::Isolated(_)
126 | InfoBridgePort::MrpRingOpen(_)
127 | InfoBridgePort::MrpInOpen(_)
128 | InfoBridgePort::Locked(_)
129 | InfoBridgePort::Mab(_)
130 | InfoBridgePort::NeighVlanSupress(_) => 1,
131 InfoBridgePort::Priority(_)
132 | InfoBridgePort::DesignatedPort(_)
133 | InfoBridgePort::DesignatedCost(_)
134 | InfoBridgePort::PortId(_)
135 | InfoBridgePort::PortNumber(_)
136 | InfoBridgePort::GroupFwdMask(_) => 2,
137 InfoBridgePort::Cost(_)
138 | InfoBridgePort::BackupPort(_)
139 | InfoBridgePort::MulticastEhtHostsLimit(_)
140 | InfoBridgePort::MulticastEhtHostsCnt(_)
141 | InfoBridgePort::MulticastNGroups(_)
142 | InfoBridgePort::MulticastMaxGroups(_)
143 | InfoBridgePort::BackupNextHopId(_) => 4,
144 InfoBridgePort::RootId(_)
145 | InfoBridgePort::BridgeId(_)
146 | InfoBridgePort::MessageAgeTimer(_)
147 | InfoBridgePort::ForwardDelayTimer(_)
148 | InfoBridgePort::HoldTimer(_) => 8,
149 InfoBridgePort::Other(nla) => nla.value_len(),
150 }
151 }
152
153 fn emit_value(&self, buffer: &mut [u8]) {
154 match self {
155 InfoBridgePort::Flush => (),
156 InfoBridgePort::HairpinMode(value)
157 | InfoBridgePort::Guard(value)
158 | InfoBridgePort::Protect(value)
159 | InfoBridgePort::FastLeave(value)
160 | InfoBridgePort::Learning(value)
161 | InfoBridgePort::UnicastFlood(value)
162 | InfoBridgePort::ProxyARP(value)
163 | InfoBridgePort::TopologyChangeAck(value)
164 | InfoBridgePort::ConfigPending(value)
165 | InfoBridgePort::ProxyARPWifi(value)
166 | InfoBridgePort::MulticastFlood(value)
167 | InfoBridgePort::MulticastToUnicast(value)
168 | InfoBridgePort::VlanTunnel(value)
169 | InfoBridgePort::BroadcastFlood(value)
170 | InfoBridgePort::NeighSupress(value)
171 | InfoBridgePort::Isolated(value)
172 | InfoBridgePort::MrpRingOpen(value)
173 | InfoBridgePort::MrpInOpen(value)
174 | InfoBridgePort::Locked(value)
175 | InfoBridgePort::Mab(value)
176 | InfoBridgePort::NeighVlanSupress(value) => {
177 buffer[0] = if *value { 1 } else { 0 }
178 }
179 InfoBridgePort::Priority(value)
180 | InfoBridgePort::DesignatedPort(value)
181 | InfoBridgePort::DesignatedCost(value)
182 | InfoBridgePort::PortId(value)
183 | InfoBridgePort::PortNumber(value)
184 | InfoBridgePort::GroupFwdMask(value) => {
185 emit_u16(buffer, *value).unwrap()
186 }
187 InfoBridgePort::Cost(value)
188 | InfoBridgePort::BackupPort(value)
189 | InfoBridgePort::MulticastEhtHostsLimit(value)
190 | InfoBridgePort::MulticastEhtHostsCnt(value)
191 | InfoBridgePort::MulticastNGroups(value)
192 | InfoBridgePort::MulticastMaxGroups(value)
193 | InfoBridgePort::BackupNextHopId(value) => {
194 emit_u32(buffer, *value).unwrap()
195 }
196 InfoBridgePort::MessageAgeTimer(value)
197 | InfoBridgePort::ForwardDelayTimer(value)
198 | InfoBridgePort::HoldTimer(value) => {
199 emit_u64(buffer, *value).unwrap()
200 }
201 InfoBridgePort::RootId(bridge_id)
202 | InfoBridgePort::BridgeId(bridge_id) => bridge_id.emit(buffer),
203 InfoBridgePort::State(state) => buffer[0] = (*state).into(),
204 InfoBridgePort::MulticastRouter(mcast_router) => {
205 buffer[0] = (*mcast_router).into()
206 }
207 InfoBridgePort::Other(nla) => nla.emit_value(buffer),
208 }
209 }
210
211 fn kind(&self) -> u16 {
212 match self {
213 InfoBridgePort::State(_) => IFLA_BRPORT_STATE,
214 InfoBridgePort::Priority(_) => IFLA_BRPORT_PRIORITY,
215 InfoBridgePort::Cost(_) => IFLA_BRPORT_COST,
216 InfoBridgePort::HairpinMode(_) => IFLA_BRPORT_MODE,
217 InfoBridgePort::Guard(_) => IFLA_BRPORT_GUARD,
218 InfoBridgePort::Protect(_) => IFLA_BRPORT_PROTECT,
219 InfoBridgePort::FastLeave(_) => IFLA_BRPORT_FAST_LEAVE,
220 InfoBridgePort::Learning(_) => IFLA_BRPORT_LEARNING,
221 InfoBridgePort::UnicastFlood(_) => IFLA_BRPORT_UNICAST_FLOOD,
222 InfoBridgePort::ProxyARP(_) => IFLA_BRPORT_PROXYARP,
223 InfoBridgePort::ProxyARPWifi(_) => IFLA_BRPORT_PROXYARP_WIFI,
224 InfoBridgePort::RootId(_) => IFLA_BRPORT_ROOT_ID,
225 InfoBridgePort::BridgeId(_) => IFLA_BRPORT_BRIDGE_ID,
226 InfoBridgePort::DesignatedPort(_) => IFLA_BRPORT_DESIGNATED_PORT,
227 InfoBridgePort::DesignatedCost(_) => IFLA_BRPORT_DESIGNATED_COST,
228 InfoBridgePort::PortId(_) => IFLA_BRPORT_ID,
229 InfoBridgePort::PortNumber(_) => IFLA_BRPORT_NO,
230 InfoBridgePort::TopologyChangeAck(_) => {
231 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
232 }
233 InfoBridgePort::ConfigPending(_) => IFLA_BRPORT_CONFIG_PENDING,
234 InfoBridgePort::MessageAgeTimer(_) => IFLA_BRPORT_MESSAGE_AGE_TIMER,
235 InfoBridgePort::ForwardDelayTimer(_) => {
236 IFLA_BRPORT_FORWARD_DELAY_TIMER
237 }
238 InfoBridgePort::HoldTimer(_) => IFLA_BRPORT_HOLD_TIMER,
239 InfoBridgePort::Flush => IFLA_BRPORT_FLUSH,
240 InfoBridgePort::MulticastRouter(_) => IFLA_BRPORT_MULTICAST_ROUTER,
241 InfoBridgePort::MulticastFlood(_) => IFLA_BRPORT_MCAST_FLOOD,
242 InfoBridgePort::MulticastToUnicast(_) => IFLA_BRPORT_MCAST_TO_UCAST,
243 InfoBridgePort::VlanTunnel(_) => IFLA_BRPORT_VLAN_TUNNEL,
244 InfoBridgePort::BroadcastFlood(_) => IFLA_BRPORT_BCAST_FLOOD,
245 InfoBridgePort::GroupFwdMask(_) => IFLA_BRPORT_GROUP_FWD_MASK,
246 InfoBridgePort::NeighSupress(_) => IFLA_BRPORT_NEIGH_SUPPRESS,
247 InfoBridgePort::Isolated(_) => IFLA_BRPORT_ISOLATED,
248 InfoBridgePort::BackupPort(_) => IFLA_BRPORT_BACKUP_PORT,
249 InfoBridgePort::MrpRingOpen(_) => IFLA_BRPORT_MRP_RING_OPEN,
250 InfoBridgePort::MrpInOpen(_) => IFLA_BRPORT_MRP_IN_OPEN,
251 InfoBridgePort::MulticastEhtHostsLimit(_) => {
252 IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT
253 }
254 InfoBridgePort::MulticastEhtHostsCnt(_) => {
255 IFLA_BRPORT_MCAST_EHT_HOSTS_CNT
256 }
257 InfoBridgePort::Locked(_) => IFLA_BRPORT_LOCKED,
258 InfoBridgePort::Mab(_) => IFLA_BRPORT_MAB,
259 InfoBridgePort::MulticastNGroups(_) => IFLA_BRPORT_MCAST_N_GROUPS,
260 InfoBridgePort::MulticastMaxGroups(_) => {
261 IFLA_BRPORT_MCAST_MAX_GROUPS
262 }
263 InfoBridgePort::NeighVlanSupress(_) => {
264 IFLA_BRPORT_NEIGH_VLAN_SUPPRESS
265 }
266 InfoBridgePort::BackupNextHopId(_) => IFLA_BRPORT_BACKUP_NHID,
267 InfoBridgePort::Other(nla) => nla.kind(),
268 }
269 }
270}
271
272impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
273 for InfoBridgePort
274{
275 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
276 let payload = buf.value();
277
278 Ok(match buf.kind() {
279 IFLA_BRPORT_STATE => InfoBridgePort::State(
280 parse_u8(payload)
281 .context({
282 format!("invalid IFLA_BRPORT_STATE {payload:?}")
283 })?
284 .into(),
285 ),
286 IFLA_BRPORT_PRIORITY => {
287 InfoBridgePort::Priority(parse_u16(payload).context({
288 format!("invalid IFLA_BRPORT_PRIORITY {payload:?}")
289 })?)
290 }
291 IFLA_BRPORT_COST => {
292 InfoBridgePort::Cost(parse_u32(payload).context({
293 format!("invalid IFLA_BRPORT_COST {payload:?}")
294 })?)
295 }
296 IFLA_BRPORT_MODE => InfoBridgePort::HairpinMode(
297 parse_u8(payload).context({
298 format!("invalid IFLA_BRPORT_MODE {payload:?}")
299 })? > 0,
300 ),
301 IFLA_BRPORT_GUARD => InfoBridgePort::Guard(
302 parse_u8(payload).context({
303 format!("invalid IFLA_BRPORT_GUARD {payload:?}")
304 })? > 0,
305 ),
306 IFLA_BRPORT_PROTECT => InfoBridgePort::Protect(
307 parse_u8(payload).context({
308 format!("invalid IFLA_BRPORT_PROTECT {payload:?}")
309 })? > 0,
310 ),
311 IFLA_BRPORT_FAST_LEAVE => InfoBridgePort::FastLeave(
312 parse_u8(payload).context({
313 format!("invalid IFLA_BRPORT_FAST_LEAVE {payload:?}")
314 })? > 0,
315 ),
316 IFLA_BRPORT_LEARNING => InfoBridgePort::Learning(
317 parse_u8(payload).context({
318 format!("invalid IFLA_BRPORT_LEARNING {payload:?}")
319 })? > 0,
320 ),
321 IFLA_BRPORT_UNICAST_FLOOD => InfoBridgePort::UnicastFlood(
322 parse_u8(payload).context({
323 format!("invalid IFLA_BRPORT_UNICAST_FLOOD {payload:?}")
324 })? > 0,
325 ),
326 IFLA_BRPORT_PROXYARP => InfoBridgePort::ProxyARP(
327 parse_u8(payload).context({
328 format!("invalid IFLA_BRPORT_PROXYARP {payload:?}")
329 })? > 0,
330 ),
331 IFLA_BRPORT_PROXYARP_WIFI => InfoBridgePort::ProxyARPWifi(
332 parse_u8(payload).context({
333 format!("invalid IFLA_BRPORT_PROXYARP_WIFI {payload:?}")
334 })? > 0,
335 ),
336 IFLA_BRPORT_ROOT_ID => Self::RootId(
337 BridgeId::parse(&BridgeIdBuffer::new(payload)).context(
338 format!("invalid IFLA_BRPORT_ROOT_ID {payload:?}"),
339 )?,
340 ),
341 IFLA_BRPORT_BRIDGE_ID => Self::BridgeId(
342 BridgeId::parse(&BridgeIdBuffer::new(payload)).context(
343 format!("invalid IFLA_BRPORT_BRIDGE_ID {payload:?}"),
344 )?,
345 ),
346 IFLA_BRPORT_DESIGNATED_PORT => {
347 InfoBridgePort::DesignatedPort(parse_u16(payload).context({
348 format!("invalid IFLA_BRPORT_DESIGNATED_PORT {payload:?}")
349 })?)
350 }
351 IFLA_BRPORT_DESIGNATED_COST => {
352 InfoBridgePort::DesignatedCost(parse_u16(payload).context({
353 format!("invalid IFLA_BRPORT_DESIGNATED_COST {payload:?}")
354 })?)
355 }
356 IFLA_BRPORT_ID => {
357 InfoBridgePort::PortId(parse_u16(payload).context({
358 format!("invalid IFLA_BRPORT_ID {payload:?}")
359 })?)
360 }
361 IFLA_BRPORT_NO => InfoBridgePort::PortNumber(
362 parse_u16(payload)
363 .context(format!("invalid IFLA_BRPORT_NO {payload:?}"))?,
364 ),
365 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK => {
366 InfoBridgePort::TopologyChangeAck(
367 parse_u8(payload).context({
368 format!(
369 "invalid IFLA_BRPORT_TOPOLOGY_CHANGE_ACK \
370 {payload:?}"
371 )
372 })? > 0,
373 )
374 }
375 IFLA_BRPORT_CONFIG_PENDING => InfoBridgePort::ConfigPending(
376 parse_u8(payload).context({
377 format!("invalid IFLA_BRPORT_CONFIG_PENDING {payload:?}")
378 })? > 0,
379 ),
380 IFLA_BRPORT_MESSAGE_AGE_TIMER => InfoBridgePort::MessageAgeTimer(
381 parse_u64(payload).context({
382 format!("invalid IFLA_BRPORT_MESSAGE_AGE_TIMER {payload:?}")
383 })?,
384 ),
385 IFLA_BRPORT_FORWARD_DELAY_TIMER => {
386 InfoBridgePort::ForwardDelayTimer(parse_u64(payload).context(
387 {
388 format!(
389 "invalid IFLA_BRPORT_FORWARD_DELAY_TIMER \
390 {payload:?}"
391 )
392 },
393 )?)
394 }
395 IFLA_BRPORT_HOLD_TIMER => {
396 InfoBridgePort::HoldTimer(parse_u64(payload).context({
397 format!("invalid IFLA_BRPORT_HOLD_TIMER {payload:?}")
398 })?)
399 }
400 IFLA_BRPORT_FLUSH => InfoBridgePort::Flush,
401 IFLA_BRPORT_MULTICAST_ROUTER => InfoBridgePort::MulticastRouter(
402 parse_u8(payload)
403 .context({
404 format!(
405 "invalid IFLA_BRPORT_MULTICAST_ROUTER {payload:?}"
406 )
407 })?
408 .into(),
409 ),
410 IFLA_BRPORT_MCAST_FLOOD => InfoBridgePort::MulticastFlood(
411 parse_u8(payload).context({
412 format!("invalid IFLA_BRPORT_MCAST_FLOOD {payload:?}")
413 })? > 0,
414 ),
415 IFLA_BRPORT_MCAST_TO_UCAST => InfoBridgePort::MulticastToUnicast(
416 parse_u8(payload).context({
417 format!("invalid IFLA_BRPORT_MCAST_TO_UCAST {payload:?}")
418 })? > 0,
419 ),
420 IFLA_BRPORT_VLAN_TUNNEL => InfoBridgePort::VlanTunnel(
421 parse_u8(payload).context({
422 format!("invalid IFLA_BRPORT_VLAN_TUNNEL {payload:?}")
423 })? > 0,
424 ),
425 IFLA_BRPORT_BCAST_FLOOD => InfoBridgePort::BroadcastFlood(
426 parse_u8(payload).context({
427 format!("invalid IFLA_BRPORT_BCAST_FLOOD {payload:?}")
428 })? > 0,
429 ),
430 IFLA_BRPORT_GROUP_FWD_MASK => {
431 InfoBridgePort::GroupFwdMask(parse_u16(payload).context({
432 format!("invalid IFLA_BRPORT_GROUP_FWD_MASK {payload:?}")
433 })?)
434 }
435 IFLA_BRPORT_NEIGH_SUPPRESS => InfoBridgePort::NeighSupress(
436 parse_u8(payload).context({
437 format!("invalid IFLA_BRPORT_NEIGH_SUPPRESS {payload:?}")
438 })? > 0,
439 ),
440 IFLA_BRPORT_ISOLATED => InfoBridgePort::Isolated(
441 parse_u8(payload).context({
442 format!("invalid IFLA_BRPORT_ISOLATED {payload:?}")
443 })? > 0,
444 ),
445 IFLA_BRPORT_BACKUP_PORT => {
446 InfoBridgePort::BackupPort(parse_u32(payload).context(
447 format!("invalid IFLA_BRPORT_BACKUP_PORT {payload:?}"),
448 )?)
449 }
450 IFLA_BRPORT_MRP_RING_OPEN => InfoBridgePort::MrpRingOpen(
451 parse_u8(payload).context({
452 format!("invalid IFLA_BRPORT_MRP_RING_OPEN {payload:?}")
453 })? > 0,
454 ),
455 IFLA_BRPORT_MRP_IN_OPEN => InfoBridgePort::MrpInOpen(
456 parse_u8(payload).context({
457 format!("invalid IFLA_BRPORT_MRP_IN_OPEN {payload:?}")
458 })? > 0,
459 ),
460 IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT => {
461 InfoBridgePort::MulticastEhtHostsLimit(
462 parse_u32(payload).context({
463 format!(
464 "invalid IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT \
465 {payload:?}"
466 )
467 })?,
468 )
469 }
470 IFLA_BRPORT_MCAST_EHT_HOSTS_CNT => {
471 InfoBridgePort::MulticastEhtHostsCnt(
472 parse_u32(payload).context({
473 format!(
474 "invalid IFLA_BRPORT_MCAST_EHT_HOSTS_CNT \
475 {payload:?}"
476 )
477 })?,
478 )
479 }
480 IFLA_BRPORT_LOCKED => InfoBridgePort::Locked(
481 parse_u8(payload).context({
482 format!("invalid IFLA_BRPORT_LOCKED {payload:?}")
483 })? > 0,
484 ),
485 IFLA_BRPORT_MAB => InfoBridgePort::Mab(
486 parse_u8(payload).context({
487 format!("invalid IFLA_BRPORT_MAB {payload:?}")
488 })? > 0,
489 ),
490 IFLA_BRPORT_MCAST_N_GROUPS => InfoBridgePort::MulticastNGroups(
491 parse_u32(payload).context({
492 format!("invalid IFLA_BRPORT_MCAST_N_GROUPS {payload:?}")
493 })?,
494 ),
495 IFLA_BRPORT_MCAST_MAX_GROUPS => InfoBridgePort::MulticastMaxGroups(
496 parse_u32(payload).context({
497 format!("invalid IFLA_BRPORT_MCAST_MAX_GROUPS {payload:?}")
498 })?,
499 ),
500 IFLA_BRPORT_NEIGH_VLAN_SUPPRESS => {
501 InfoBridgePort::NeighVlanSupress(
502 parse_u8(payload).context({
503 format!(
504 "invalid IFLA_BRPORT_NEIGH_VLAN_SUPPRESS \
505 {payload:?}"
506 )
507 })? > 0,
508 )
509 }
510 IFLA_BRPORT_BACKUP_NHID => {
511 InfoBridgePort::BackupNextHopId(parse_u32(payload).context(
512 format!("invalid IFLA_BRPORT_BACKUP_NHID {payload:?}"),
513 )?)
514 }
515 kind => InfoBridgePort::Other(DefaultNla::parse(buf).context({
516 format!(
517 "failed to parse bridge port NLA of type '{kind}' into \
518 DefaultNla"
519 )
520 })?),
521 })
522 }
523}
524
525const BR_STATE_DISABLED: u8 = 0;
526const BR_STATE_LISTENING: u8 = 1;
527const BR_STATE_LEARNING: u8 = 2;
528const BR_STATE_FORWARDING: u8 = 3;
529const BR_STATE_BLOCKING: u8 = 4;
530
531#[derive(Debug, Clone, Copy, Eq, PartialEq)]
532#[non_exhaustive]
533pub enum BridgePortState {
534 Disabled,
535 Listening,
536 Learning,
537 Forwarding,
538 Blocking,
539 Other(u8),
540}
541
542impl From<u8> for BridgePortState {
543 fn from(value: u8) -> Self {
544 match value {
545 BR_STATE_DISABLED => BridgePortState::Disabled,
546 BR_STATE_LISTENING => BridgePortState::Listening,
547 BR_STATE_LEARNING => BridgePortState::Learning,
548 BR_STATE_FORWARDING => BridgePortState::Forwarding,
549 BR_STATE_BLOCKING => BridgePortState::Blocking,
550 _ => BridgePortState::Other(value),
551 }
552 }
553}
554
555impl From<BridgePortState> for u8 {
556 fn from(value: BridgePortState) -> Self {
557 match value {
558 BridgePortState::Disabled => BR_STATE_DISABLED,
559 BridgePortState::Listening => BR_STATE_LISTENING,
560 BridgePortState::Learning => BR_STATE_LEARNING,
561 BridgePortState::Forwarding => BR_STATE_FORWARDING,
562 BridgePortState::Blocking => BR_STATE_BLOCKING,
563 BridgePortState::Other(v) => v,
564 }
565 }
566}
567
568const MDB_RTR_TYPE_DISABLED: u8 = 0;
569const MDB_RTR_TYPE_TEMP_QUERY: u8 = 1;
570const MDB_RTR_TYPE_PERM: u8 = 2;
571const MDB_RTR_TYPE_TEMP: u8 = 3;
572
573#[derive(Debug, Clone, Copy, Eq, PartialEq)]
574#[non_exhaustive]
575pub enum BridgePortMulticastRouter {
576 Disabled,
577 TempQuery,
578 Perm,
579 Temp,
580 Other(u8),
581}
582
583impl From<u8> for BridgePortMulticastRouter {
584 fn from(value: u8) -> Self {
585 match value {
586 MDB_RTR_TYPE_DISABLED => BridgePortMulticastRouter::Disabled,
587 MDB_RTR_TYPE_TEMP_QUERY => BridgePortMulticastRouter::TempQuery,
588 MDB_RTR_TYPE_PERM => BridgePortMulticastRouter::Perm,
589 MDB_RTR_TYPE_TEMP => BridgePortMulticastRouter::Temp,
590 _ => BridgePortMulticastRouter::Other(value),
591 }
592 }
593}
594
595impl From<BridgePortMulticastRouter> for u8 {
596 fn from(value: BridgePortMulticastRouter) -> Self {
597 match value {
598 BridgePortMulticastRouter::Disabled => MDB_RTR_TYPE_DISABLED,
599 BridgePortMulticastRouter::TempQuery => MDB_RTR_TYPE_TEMP_QUERY,
600 BridgePortMulticastRouter::Perm => MDB_RTR_TYPE_PERM,
601 BridgePortMulticastRouter::Temp => MDB_RTR_TYPE_TEMP,
602 BridgePortMulticastRouter::Other(v) => v,
603 }
604 }
605}