netlink_packet_route/link/link_info/
ipvlan.rs
1use 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}