netlink_packet_route/link/link_info/
ipvlan.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::parse_u16;
7use netlink_packet_utils::traits::Parseable;
8use netlink_packet_utils::DecodeError;
9
10const IFLA_IPVLAN_MODE: u16 = 1;
11const IFLA_IPVLAN_FLAGS: u16 = 2;
12
13#[derive(Debug, PartialEq, Eq, Clone)]
14#[non_exhaustive]
15pub enum InfoIpVlan {
16    Mode(IpVlanMode),
17    Flags(u16),
18    Other(DefaultNla),
19}
20
21impl Nla for InfoIpVlan {
22    fn value_len(&self) -> usize {
23        use self::InfoIpVlan::*;
24        match self {
25            Mode(_) | Flags(_) => 2,
26            Other(nla) => nla.value_len(),
27        }
28    }
29
30    fn emit_value(&self, buffer: &mut [u8]) {
31        use self::InfoIpVlan::*;
32        match self {
33            Mode(value) => NativeEndian::write_u16(buffer, (*value).into()),
34            Flags(value) => NativeEndian::write_u16(buffer, *value),
35            Other(nla) => nla.emit_value(buffer),
36        }
37    }
38
39    fn kind(&self) -> u16 {
40        use self::InfoIpVlan::*;
41        match self {
42            Mode(_) => IFLA_IPVLAN_MODE,
43            Flags(_) => IFLA_IPVLAN_FLAGS,
44            Other(nla) => nla.kind(),
45        }
46    }
47}
48
49impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVlan {
50    type Error = DecodeError;
51    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
52        use self::InfoIpVlan::*;
53        let payload = buf.value();
54        Ok(match buf.kind() {
55            IFLA_IPVLAN_MODE => {
56                Mode(parse_u16(payload).context("invalid IFLA_IPVLAN_MODE value")?.into())
57            }
58            IFLA_IPVLAN_FLAGS => {
59                Flags(parse_u16(payload).context("invalid IFLA_IPVLAN_FLAGS value")?)
60            }
61            kind => Other(
62                DefaultNla::parse(buf)
63                    .context(format!("unknown NLA type {kind} for IFLA_INFO_DATA(ipvlan)"))?,
64            ),
65        })
66    }
67}
68
69#[derive(Debug, PartialEq, Eq, Clone)]
70#[non_exhaustive]
71pub enum InfoIpVtap {
72    Mode(IpVtapMode),
73    Flags(u16),
74    Other(DefaultNla),
75}
76
77impl Nla for InfoIpVtap {
78    fn value_len(&self) -> usize {
79        use self::InfoIpVtap::*;
80        match self {
81            Mode(_) | Flags(_) => 2,
82            Other(nla) => nla.value_len(),
83        }
84    }
85
86    fn emit_value(&self, buffer: &mut [u8]) {
87        use self::InfoIpVtap::*;
88        match self {
89            Mode(value) => NativeEndian::write_u16(buffer, (*value).into()),
90            Flags(value) => NativeEndian::write_u16(buffer, *value),
91            Other(nla) => nla.emit_value(buffer),
92        }
93    }
94
95    fn kind(&self) -> u16 {
96        use self::InfoIpVtap::*;
97        match self {
98            Mode(_) => IFLA_IPVLAN_MODE,
99            Flags(_) => IFLA_IPVLAN_FLAGS,
100            Other(nla) => nla.kind(),
101        }
102    }
103}
104
105impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVtap {
106    type Error = DecodeError;
107    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
108        use self::InfoIpVtap::*;
109        let payload = buf.value();
110        Ok(match buf.kind() {
111            IFLA_IPVLAN_MODE => {
112                Mode(parse_u16(payload).context("invalid IFLA_IPVLAN_MODE value")?.into())
113            }
114            IFLA_IPVLAN_FLAGS => {
115                Flags(parse_u16(payload).context("invalid IFLA_IPVLAN_FLAGS value")?)
116            }
117            kind => Other(
118                DefaultNla::parse(buf)
119                    .context(format!("unknown NLA type {kind} for IFLA_INFO_DATA(ipvlan)"))?,
120            ),
121        })
122    }
123}
124
125const IPVLAN_MODE_L2: u16 = 0;
126const IPVLAN_MODE_L3: u16 = 1;
127const IPVLAN_MODE_L3S: u16 = 2;
128
129#[derive(Debug, PartialEq, Eq, Clone, Copy)]
130#[non_exhaustive]
131pub enum IpVlanMode {
132    L2,
133    L3,
134    L3S,
135    Other(u16),
136}
137
138pub type IpVtapMode = IpVlanMode;
139
140impl From<u16> for IpVlanMode {
141    fn from(d: u16) -> Self {
142        match d {
143            IPVLAN_MODE_L2 => Self::L2,
144            IPVLAN_MODE_L3 => Self::L3,
145            IPVLAN_MODE_L3S => Self::L3S,
146            _ => {
147                log::warn!("Unknown IP VLAN mode {}", d);
148                Self::Other(d)
149            }
150        }
151    }
152}
153
154impl From<IpVlanMode> for u16 {
155    fn from(v: IpVlanMode) -> u16 {
156        match v {
157            IpVlanMode::L2 => IPVLAN_MODE_L2,
158            IpVlanMode::L3 => IPVLAN_MODE_L3,
159            IpVlanMode::L3S => IPVLAN_MODE_L3S,
160            IpVlanMode::Other(d) => d,
161        }
162    }
163}