Skip to content

Commit 7649424

Browse files
authored
Merge branch 'main' into seg6
2 parents d327d20 + 1bab123 commit 7649424

32 files changed

+1400
-165
lines changed

CHANGELOG

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11
# Changelog
2+
## [0.21.0] - 2024-09-12
3+
### Breaking changes
4+
- `InfoIpVlan::Flags` changed from u16 to `IpVlanFlags`. (321e4d5)
5+
- `AfSpecBridge::Flags` changed from u16 to `BridgeFlag`. (40d090b)
6+
- `InfoBond::ArpValidate` changed from u32 to `BondArpValidate`.(5246712)
7+
- `InfoVxlan::Group` changed from `Vec<u8>` to `Ipv4Addr`. (538e13b)
8+
- `InfoVxlan::Group6` changed from `Vec<u8>` to `Ipv6Addr`. (538e13b)
9+
- `InfoVxlan::Local` changed from `Vec<u8>` to `Ipv4Addr`. (538e13b)
10+
- `InfoVxlan::Local6` changed from `Vec<u8>` to `Ipv6Addr`. (538e13b)
11+
12+
### New features
13+
- bridge port: Introduce BridgeFlag, BridgeMode and BridgeVlanTunnelInfo.
14+
(40d090b)
15+
- Add support for geneve links. (7391b19)
16+
17+
### Bug fixes
18+
- Avoid panic in TcU32Selector parsing. (c49e3ac)
19+
- Avoid panic in RouteNextHopBuffer length checks. (666edbc)
20+
- Check NLA buffers on creation. (fceb9c2)
21+
- Check Map buffers on creation. (d53bbad)
22+
223
## [0.20.1] - 2024-06-29
324
### Breaking changes
425
- N/A

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
authors = ["Corentin Henry <corentinhenry@gmail.com>"]
33
name = "netlink-packet-route"
4-
version = "0.20.1"
4+
version = "0.21.0"
55
edition = "2021"
66

77
homepage = "https://github.com/rust-netlink/netlink-packet-route"

src/link/af_spec/bridge.rs

Lines changed: 251 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,98 @@
33
use anyhow::Context;
44
use byteorder::{ByteOrder, NativeEndian};
55
use netlink_packet_utils::{
6-
nla::{self, DefaultNla, NlaBuffer},
7-
parsers::parse_u16,
6+
nla::{DefaultNla, Nla, NlaBuffer, NlasIterator},
7+
parsers::{parse_u16, parse_u32},
88
traits::Parseable,
9-
DecodeError,
9+
DecodeError, Emitable,
1010
};
1111

1212
const IFLA_BRIDGE_FLAGS: u16 = 0;
13+
const IFLA_BRIDGE_MODE: u16 = 1;
1314
const IFLA_BRIDGE_VLAN_INFO: u16 = 2;
15+
const IFLA_BRIDGE_VLAN_TUNNEL_INFO: u16 = 3;
16+
// const IFLA_BRIDGE_MRP: u16 = 4;
17+
// const IFLA_BRIDGE_CFM: u16 = 5;
18+
// const IFLA_BRIDGE_MST: u16 = 6;
1419

1520
#[derive(Clone, Eq, PartialEq, Debug)]
1621
#[non_exhaustive]
1722
pub enum AfSpecBridge {
18-
Flags(u16),
23+
Flags(BridgeFlag),
24+
Mode(BridgeMode),
1925
VlanInfo(BridgeVlanInfo),
26+
VlanTunnelInfo(Vec<BridgeVlanTunnelInfo>),
2027
Other(DefaultNla),
2128
}
2229

23-
impl nla::Nla for AfSpecBridge {
30+
impl Nla for AfSpecBridge {
2431
fn value_len(&self) -> usize {
25-
use self::AfSpecBridge::*;
26-
match *self {
27-
VlanInfo(_) => 4,
28-
Flags(_) => 2,
29-
Other(ref nla) => nla.value_len(),
32+
match self {
33+
Self::Flags(_) => BridgeFlag::LENGTH,
34+
Self::Mode(_) => BridgeMode::LENGTH,
35+
Self::VlanInfo(_) => BridgeVlanInfo::LENGTH,
36+
Self::VlanTunnelInfo(s) => s.as_slice().buffer_len(),
37+
Self::Other(nla) => nla.value_len(),
3038
}
3139
}
3240

3341
fn emit_value(&self, buffer: &mut [u8]) {
34-
use self::AfSpecBridge::*;
35-
match *self {
36-
Flags(value) => NativeEndian::write_u16(buffer, value),
37-
VlanInfo(ref info) => {
42+
match self {
43+
Self::Flags(value) => {
44+
NativeEndian::write_u16(buffer, u16::from(*value))
45+
}
46+
Self::Mode(value) => {
47+
NativeEndian::write_u16(buffer, u16::from(*value))
48+
}
49+
Self::VlanInfo(info) => {
3850
buffer[..4].copy_from_slice(<[u8; 4]>::from(info).as_slice())
3951
}
40-
Other(ref nla) => nla.emit_value(buffer),
52+
Self::VlanTunnelInfo(s) => s.as_slice().emit(buffer),
53+
Self::Other(nla) => nla.emit_value(buffer),
4154
}
4255
}
4356

4457
fn kind(&self) -> u16 {
45-
use self::AfSpecBridge::*;
46-
match *self {
47-
Flags(_) => IFLA_BRIDGE_FLAGS,
48-
VlanInfo(_) => IFLA_BRIDGE_VLAN_INFO,
49-
Other(ref nla) => nla.kind(),
58+
match self {
59+
Self::Flags(_) => IFLA_BRIDGE_FLAGS,
60+
Self::Mode(_) => IFLA_BRIDGE_MODE,
61+
Self::VlanInfo(_) => IFLA_BRIDGE_VLAN_INFO,
62+
Self::VlanTunnelInfo(_) => IFLA_BRIDGE_VLAN_TUNNEL_INFO,
63+
Self::Other(nla) => nla.kind(),
5064
}
5165
}
5266
}
5367

5468
impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for AfSpecBridge {
5569
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
56-
use self::AfSpecBridge::*;
57-
5870
let payload = buf.value();
5971
Ok(match buf.kind() {
60-
IFLA_BRIDGE_VLAN_INFO => VlanInfo(
61-
BridgeVlanInfo::try_from(payload)
62-
.context("Invalid IFLA_BRIDGE_VLAN_INFO value")?,
72+
IFLA_BRIDGE_FLAGS => Self::Flags(
73+
parse_u16(payload)
74+
.context("Invalid IFLA_BRIDGE_FLAGS value")?
75+
.into(),
6376
),
64-
IFLA_BRIDGE_FLAGS => Flags(
77+
IFLA_BRIDGE_MODE => Self::Mode(
6578
parse_u16(payload)
66-
.context("invalid IFLA_BRIDGE_FLAGS value")?,
79+
.context("Invalid IFLA_BRIDGE_MODE value")?
80+
.into(),
6781
),
68-
kind => Other(
82+
IFLA_BRIDGE_VLAN_INFO => Self::VlanInfo(
83+
BridgeVlanInfo::try_from(payload)
84+
.context("Invalid IFLA_BRIDGE_VLAN_INFO value")?,
85+
),
86+
IFLA_BRIDGE_VLAN_TUNNEL_INFO => {
87+
let mut nlas = Vec::new();
88+
for nla in NlasIterator::new(payload) {
89+
let nla = &nla.context(format!(
90+
"Invalid IFLA_BRIDGE_VLAN_TUNNEL_INFO for {payload:?}"
91+
))?;
92+
let parsed = BridgeVlanTunnelInfo::parse(nla)?;
93+
nlas.push(parsed);
94+
}
95+
Self::VlanTunnelInfo(nlas)
96+
}
97+
kind => Self::Other(
6998
DefaultNla::parse(buf)
7099
.context(format!("Unknown NLA type {kind}"))?,
71100
),
@@ -83,27 +112,62 @@ impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
83112
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
84113
let mut nlas = vec![];
85114
let err = "Invalid AF_INET NLA for IFLA_AF_SPEC(AF_BRIDGE)";
86-
for nla in
87-
netlink_packet_utils::nla::NlasIterator::new(buf.into_inner())
88-
{
115+
for nla in NlasIterator::new(buf.into_inner()) {
89116
let nla = nla.context(err)?;
90117
nlas.push(AfSpecBridge::parse(&nla).context(err)?);
91118
}
92119
Ok(Self(nlas))
93120
}
94121
}
95122

96-
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
97-
#[non_exhaustive]
123+
const BRIDGE_VLAN_INFO_CONTROLLER: u16 = 1 << 0;
124+
const BRIDGE_VLAN_INFO_PVID: u16 = 1 << 1;
125+
const BRIDGE_VLAN_INFO_UNTAGGED: u16 = 1 << 2;
126+
const BRIDGE_VLAN_INFO_RANGE_BEGIN: u16 = 1 << 3;
127+
const BRIDGE_VLAN_INFO_RANGE_END: u16 = 1 << 4;
128+
const BRIDGE_VLAN_INFO_BRENTRY: u16 = 1 << 5;
129+
const BRIDGE_VLAN_INFO_ONLY_OPTS: u16 = 1 << 6;
130+
131+
bitflags! {
132+
#[non_exhaustive]
133+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
134+
pub struct BridgeVlanInfoFlags: u16 {
135+
/// Operate on Bridge device as well
136+
const Controller = BRIDGE_VLAN_INFO_CONTROLLER;
137+
/// VLAN is PVID, ingress untagged
138+
const Pvid = BRIDGE_VLAN_INFO_PVID;
139+
/// VLAN egresses untagged
140+
const Untagged= BRIDGE_VLAN_INFO_UNTAGGED;
141+
/// VLAN is start of vlan range
142+
const RangeBegin = BRIDGE_VLAN_INFO_RANGE_BEGIN;
143+
/// VLAN is end of vlan range
144+
const RangeEnd = BRIDGE_VLAN_INFO_RANGE_END;
145+
/// Global bridge VLAN entry
146+
const Brentry = BRIDGE_VLAN_INFO_BRENTRY;
147+
/// Skip create/delete/flags
148+
const OnlyOpts= BRIDGE_VLAN_INFO_ONLY_OPTS;
149+
const _ = !0;
150+
}
151+
}
152+
153+
impl BridgeVlanInfoFlags {
154+
pub const LENGTH: usize = 2;
155+
}
156+
157+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
98158
pub struct BridgeVlanInfo {
99-
pub flags: u16,
159+
pub flags: BridgeVlanInfoFlags,
100160
pub vid: u16,
101161
}
102162

163+
impl BridgeVlanInfo {
164+
pub const LENGTH: usize = 4;
165+
}
166+
103167
impl From<&BridgeVlanInfo> for [u8; 4] {
104168
fn from(d: &BridgeVlanInfo) -> Self {
105169
let mut ret = [0u8; 4];
106-
NativeEndian::write_u16(&mut ret[0..2], d.flags);
170+
NativeEndian::write_u16(&mut ret[0..2], d.flags.bits());
107171
NativeEndian::write_u16(&mut ret[2..4], d.vid);
108172
ret
109173
}
@@ -114,9 +178,11 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
114178
fn try_from(raw: &[u8]) -> Result<Self, DecodeError> {
115179
if raw.len() == 4 {
116180
Ok(Self {
117-
flags: parse_u16(&raw[0..2]).context(format!(
118-
"Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
119-
))?,
181+
flags: BridgeVlanInfoFlags::from_bits_retain(
182+
parse_u16(&raw[0..2]).context(format!(
183+
"Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
184+
))?,
185+
),
120186
vid: parse_u16(&raw[2..4]).context(format!(
121187
"Invalid IFLA_BRIDGE_VLAN_INFO value: {raw:?}"
122188
))?,
@@ -129,3 +195,150 @@ impl TryFrom<&[u8]> for BridgeVlanInfo {
129195
}
130196
}
131197
}
198+
199+
// kernel constant name is BRIDGE_FLAGS_MASTER
200+
const BRIDGE_FLAGS_CONTROLLER: u16 = 1;
201+
const BRIDGE_FLAGS_SELF: u16 = 2;
202+
203+
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
204+
#[non_exhaustive]
205+
pub enum BridgeFlag {
206+
/// Bridge command to/from controller
207+
Controller,
208+
/// Bridge command to/from lowerdev
209+
LowerDev,
210+
Other(u16),
211+
}
212+
213+
impl From<u16> for BridgeFlag {
214+
fn from(d: u16) -> Self {
215+
match d {
216+
BRIDGE_FLAGS_CONTROLLER => Self::Controller,
217+
BRIDGE_FLAGS_SELF => Self::LowerDev,
218+
_ => Self::Other(d),
219+
}
220+
}
221+
}
222+
223+
impl From<BridgeFlag> for u16 {
224+
fn from(v: BridgeFlag) -> u16 {
225+
match v {
226+
BridgeFlag::Controller => BRIDGE_FLAGS_CONTROLLER,
227+
BridgeFlag::LowerDev => BRIDGE_FLAGS_SELF,
228+
BridgeFlag::Other(d) => d,
229+
}
230+
}
231+
}
232+
233+
impl BridgeFlag {
234+
pub const LENGTH: usize = 2;
235+
}
236+
237+
const BRIDGE_MODE_VEB: u16 = 0;
238+
const BRIDGE_MODE_VEPA: u16 = 1;
239+
240+
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
241+
#[non_exhaustive]
242+
pub enum BridgeMode {
243+
/// Default loopback mode
244+
Veb,
245+
/// 802.1Qbg defined VEPA mode
246+
Vepa,
247+
Other(u16),
248+
}
249+
250+
impl From<u16> for BridgeMode {
251+
fn from(d: u16) -> Self {
252+
match d {
253+
BRIDGE_MODE_VEB => Self::Veb,
254+
BRIDGE_MODE_VEPA => Self::Vepa,
255+
_ => Self::Other(d),
256+
}
257+
}
258+
}
259+
260+
impl From<BridgeMode> for u16 {
261+
fn from(v: BridgeMode) -> u16 {
262+
match v {
263+
BridgeMode::Veb => BRIDGE_MODE_VEB,
264+
BridgeMode::Vepa => BRIDGE_MODE_VEPA,
265+
BridgeMode::Other(d) => d,
266+
}
267+
}
268+
}
269+
270+
impl BridgeMode {
271+
pub const LENGTH: usize = 2;
272+
}
273+
274+
const IFLA_BRIDGE_VLAN_TUNNEL_ID: u16 = 1;
275+
const IFLA_BRIDGE_VLAN_TUNNEL_VID: u16 = 2;
276+
const IFLA_BRIDGE_VLAN_TUNNEL_FLAGS: u16 = 3;
277+
278+
#[derive(Clone, Eq, PartialEq, Debug)]
279+
#[non_exhaustive]
280+
pub enum BridgeVlanTunnelInfo {
281+
Id(u32),
282+
Vid(u16),
283+
Flags(BridgeVlanInfoFlags),
284+
Other(DefaultNla),
285+
}
286+
287+
impl Nla for BridgeVlanTunnelInfo {
288+
fn value_len(&self) -> usize {
289+
match self {
290+
Self::Id(_) => 4,
291+
Self::Vid(_) => 2,
292+
Self::Flags(_) => BridgeVlanInfoFlags::LENGTH,
293+
Self::Other(nla) => nla.value_len(),
294+
}
295+
}
296+
297+
fn emit_value(&self, buffer: &mut [u8]) {
298+
match self {
299+
Self::Id(v) => NativeEndian::write_u32(buffer, *v),
300+
Self::Vid(v) => NativeEndian::write_u16(buffer, *v),
301+
Self::Flags(value) => NativeEndian::write_u16(buffer, value.bits()),
302+
Self::Other(nla) => nla.emit_value(buffer),
303+
}
304+
}
305+
306+
fn kind(&self) -> u16 {
307+
match self {
308+
Self::Id(_) => IFLA_BRIDGE_VLAN_TUNNEL_ID,
309+
Self::Vid(_) => IFLA_BRIDGE_VLAN_TUNNEL_VID,
310+
Self::Flags(_) => IFLA_BRIDGE_VLAN_TUNNEL_FLAGS,
311+
Self::Other(nla) => nla.kind(),
312+
}
313+
}
314+
}
315+
316+
impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
317+
for BridgeVlanTunnelInfo
318+
{
319+
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
320+
let payload = buf.value();
321+
Ok(match buf.kind() {
322+
IFLA_BRIDGE_VLAN_TUNNEL_ID => {
323+
Self::Id(parse_u32(payload).context(format!(
324+
"Invalid IFLA_BRIDGE_VLAN_TUNNEL_ID {payload:?}"
325+
))?)
326+
}
327+
IFLA_BRIDGE_VLAN_TUNNEL_VID => {
328+
Self::Vid(parse_u16(payload).context(format!(
329+
"Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
330+
))?)
331+
}
332+
IFLA_BRIDGE_VLAN_TUNNEL_FLAGS => {
333+
Self::Flags(BridgeVlanInfoFlags::from_bits_retain(
334+
parse_u16(payload).context(format!(
335+
"Invalid IFLA_BRIDGE_VLAN_TUNNEL_VID {payload:?}"
336+
))?,
337+
))
338+
}
339+
_ => {
340+
Self::Other(DefaultNla::parse(buf).context("Unknown NLA type")?)
341+
}
342+
})
343+
}
344+
}

0 commit comments

Comments
 (0)