netlink_packet_route/link/link_info/
ipvlan.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    emit_u16, parse_u16, DecodeError, DefaultNla, ErrorContext, Nla, NlaBuffer,
5    Parseable,
6};
7
8const IFLA_IPVLAN_MODE: u16 = 1;
9const IFLA_IPVLAN_FLAGS: u16 = 2;
10
11#[derive(Debug, PartialEq, Eq, Clone)]
12#[non_exhaustive]
13pub enum InfoIpVlan {
14    Mode(IpVlanMode),
15    Flags(IpVlanFlags),
16    Other(DefaultNla),
17}
18
19impl Nla for InfoIpVlan {
20    fn value_len(&self) -> usize {
21        use self::InfoIpVlan::*;
22        match self {
23            Mode(_) | Flags(_) => 2,
24            Other(nla) => nla.value_len(),
25        }
26    }
27
28    fn emit_value(&self, buffer: &mut [u8]) {
29        use self::InfoIpVlan::*;
30        match self {
31            Mode(value) => emit_u16(buffer, (*value).into()).unwrap(),
32            Flags(f) => emit_u16(buffer, f.bits()).unwrap(),
33            Other(nla) => nla.emit_value(buffer),
34        }
35    }
36
37    fn kind(&self) -> u16 {
38        use self::InfoIpVlan::*;
39        match self {
40            Mode(_) => IFLA_IPVLAN_MODE,
41            Flags(_) => IFLA_IPVLAN_FLAGS,
42            Other(nla) => nla.kind(),
43        }
44    }
45}
46
47impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVlan {
48    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
49        use self::InfoIpVlan::*;
50        let payload = buf.value();
51        Ok(match buf.kind() {
52            IFLA_IPVLAN_MODE => Mode(
53                parse_u16(payload)
54                    .context("invalid IFLA_IPVLAN_MODE value")?
55                    .into(),
56            ),
57            IFLA_IPVLAN_FLAGS => Self::Flags(IpVlanFlags::from_bits_retain(
58                parse_u16(payload)
59                    .context("failed to parse IFLA_IPVLAN_FLAGS")?,
60            )),
61            kind => Other(DefaultNla::parse(buf).context(format!(
62                "unknown NLA type {kind} for IFLA_INFO_DATA(ipvlan)"
63            ))?),
64        })
65    }
66}
67
68#[derive(Debug, PartialEq, Eq, Clone)]
69#[non_exhaustive]
70pub enum InfoIpVtap {
71    Mode(IpVtapMode),
72    Flags(IpVtapFlags),
73    Other(DefaultNla),
74}
75
76impl Nla for InfoIpVtap {
77    fn value_len(&self) -> usize {
78        use self::InfoIpVtap::*;
79        match self {
80            Mode(_) | Flags(_) => 2,
81            Other(nla) => nla.value_len(),
82        }
83    }
84
85    fn emit_value(&self, buffer: &mut [u8]) {
86        use self::InfoIpVtap::*;
87        match self {
88            Mode(value) => emit_u16(buffer, (*value).into()).unwrap(),
89            Flags(f) => emit_u16(buffer, f.bits()).unwrap(),
90            Other(nla) => nla.emit_value(buffer),
91        }
92    }
93
94    fn kind(&self) -> u16 {
95        use self::InfoIpVtap::*;
96        match self {
97            Mode(_) => IFLA_IPVLAN_MODE,
98            Flags(_) => IFLA_IPVLAN_FLAGS,
99            Other(nla) => nla.kind(),
100        }
101    }
102}
103
104impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for InfoIpVtap {
105    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
106        use self::InfoIpVtap::*;
107        let payload = buf.value();
108        Ok(match buf.kind() {
109            IFLA_IPVLAN_MODE => Mode(
110                parse_u16(payload)
111                    .context("invalid IFLA_IPVLAN_MODE value")?
112                    .into(),
113            ),
114            IFLA_IPVLAN_FLAGS => Self::Flags(IpVtapFlags::from_bits_retain(
115                parse_u16(payload)
116                    .context("failed to parse IFLA_IPVLAN_FLAGS")?,
117            )),
118            kind => Other(DefaultNla::parse(buf).context(format!(
119                "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}
164
165const IPVLAN_F_PRIVATE: u16 = 0x01;
166const IPVLAN_F_VEPA: u16 = 0x02;
167
168bitflags! {
169    #[non_exhaustive]
170    #[derive(Debug, Clone, Copy, Eq, PartialEq)]
171    pub struct IpVlanFlags: u16 {
172        const Private = IPVLAN_F_PRIVATE;
173        const Vepa = IPVLAN_F_VEPA;
174        const _ = !0;
175    }
176}
177
178impl Default for IpVlanFlags {
179    fn default() -> Self {
180        Self::empty()
181    }
182}
183
184pub type IpVtapFlags = IpVlanFlags;