Skip to content

Commit bcddc75

Browse files
author
Erich Heine
committed
Re #21 - Add matchall filter type
This tc filter matches all packets that encounter it.
1 parent 75ce74c commit bcddc75

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

src/rtnl/tc/constants.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ pub const TC_H_MIN_PRIORITY: u32 = 0xFFE0;
2020
pub const TC_H_MIN_INGRESS: u32 = 0xFFF2;
2121
pub const TC_H_MIN_EGRESS: u32 = 0xFFF3;
2222

23+
// matchall filters
24+
pub const TCA_MATCHALL_UNSPEC: u16 = 0;
25+
pub const TCA_MATCHALL_CLASSID: u16 = 1;
26+
pub const TCA_MATCHALL_ACT: u16 = 2;
27+
pub const TCA_MATCHALL_FLAGS: u16 = 3;
28+
pub const TCA_MATCHALL_PCNT: u16 = 4;
29+
pub const TCA_MATCHALL_PAD: u16 = 5;
30+
pub const TCA_MATCHALL_MAX: u16 = TCA_MATCHALL_PAD;
31+
2332
/// U32 filters
2433
pub const TCA_U32_UNSPEC: u16 = 0;
2534
pub const TCA_U32_CLASSID: u16 = 1;

src/rtnl/tc/nlas/filter/matchall.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
/// Matchall filter
4+
///
5+
/// Matches all packets and performs an action on them.
6+
use anyhow::Context;
7+
use byteorder::{ByteOrder, NativeEndian};
8+
use netlink_packet_utils::{
9+
nla::{self, DefaultNla, NlaBuffer, NlasIterator},
10+
parsers::parse_u32,
11+
traits::{Emitable, Parseable},
12+
DecodeError,
13+
};
14+
15+
use crate::tc::{constants::*, Action};
16+
pub const KIND: &str = "matchall";
17+
18+
#[derive(Debug, PartialEq, Eq, Clone)]
19+
#[non_exhaustive]
20+
pub enum Nla {
21+
Unspec(Vec<u8>),
22+
ClassId(u32),
23+
Act(Vec<Action>),
24+
Pcnt(Vec<u8>),
25+
Flags(u32),
26+
Other(DefaultNla),
27+
}
28+
29+
impl nla::Nla for Nla {
30+
fn value_len(&self) -> usize {
31+
use self::Nla::*;
32+
match self {
33+
Unspec(b) | Pcnt(b) => b.len(),
34+
ClassId(_) | Flags(_) => 4,
35+
Act(acts) => acts.as_slice().buffer_len(),
36+
Other(attr) => attr.value_len(),
37+
}
38+
}
39+
40+
fn emit_value(&self, buffer: &mut [u8]) {
41+
use self::Nla::*;
42+
match self {
43+
Unspec(b) | Pcnt(b) => buffer.copy_from_slice(b.as_slice()),
44+
ClassId(i) | Flags(i) => NativeEndian::write_u32(buffer, *i),
45+
Act(acts) => acts.as_slice().emit(buffer),
46+
Other(attr) => attr.emit_value(buffer),
47+
}
48+
}
49+
50+
fn kind(&self) -> u16 {
51+
use self::Nla::*;
52+
match self {
53+
Unspec(_) => TCA_MATCHALL_UNSPEC,
54+
ClassId(_) => TCA_MATCHALL_CLASSID,
55+
Act(_) => TCA_MATCHALL_ACT,
56+
Pcnt(_) => TCA_MATCHALL_PCNT,
57+
Flags(_) => TCA_MATCHALL_FLAGS,
58+
Other(attr) => attr.kind(),
59+
}
60+
}
61+
}
62+
63+
impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
64+
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
65+
use self::Nla::*;
66+
let payload = buf.value();
67+
Ok(match buf.kind() {
68+
TCA_MATCHALL_UNSPEC => Unspec(payload.to_vec()),
69+
TCA_MATCHALL_CLASSID => ClassId(
70+
parse_u32(payload)
71+
.context("failed to parse TCA_MATCHALL_UNSPEC")?,
72+
),
73+
TCA_MATCHALL_ACT => {
74+
let mut acts = vec![];
75+
for act in NlasIterator::new(payload) {
76+
let act = act.context("invalid TCA_MATCHALL_ACT")?;
77+
acts.push(
78+
Action::parse(&act)
79+
.context("failed to parse TCA_MATCHALL_ACT")?,
80+
);
81+
}
82+
Act(acts)
83+
}
84+
TCA_MATCHALL_PCNT => Pcnt(payload.to_vec()),
85+
TCA_MATCHALL_FLAGS => Flags(
86+
parse_u32(payload)
87+
.context("failed to parse TCA_MATCHALL_FLAGS")?,
88+
),
89+
_ => Other(
90+
DefaultNla::parse(buf).context("failed to parse u32 nla")?,
91+
),
92+
})
93+
}
94+
}

src/rtnl/tc/nlas/filter/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// SPDX-License-Identifier: MIT
22

3+
pub mod matchall;
34
pub mod u32;

src/rtnl/tc/nlas/options.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use netlink_packet_utils::{
77
DecodeError,
88
};
99

10-
use crate::tc::{ingress, u32};
10+
use crate::tc::{ingress, matchall, u32};
1111

1212
#[derive(Debug, PartialEq, Eq, Clone)]
1313
#[non_exhaustive]
@@ -16,6 +16,8 @@ pub enum TcOpt {
1616
Ingress,
1717
// Filter specific options
1818
U32(u32::Nla),
19+
// matchall options
20+
Matchall(matchall::Nla),
1921
// Other options
2022
Other(DefaultNla),
2123
}
@@ -25,6 +27,7 @@ impl nla::Nla for TcOpt {
2527
match self {
2628
Self::Ingress => 0,
2729
Self::U32(u) => u.value_len(),
30+
Self::Matchall(m) => m.value_len(),
2831
Self::Other(o) => o.value_len(),
2932
}
3033
}
@@ -33,6 +36,7 @@ impl nla::Nla for TcOpt {
3336
match self {
3437
Self::Ingress => unreachable!(),
3538
Self::U32(u) => u.emit_value(buffer),
39+
Self::Matchall(m) => m.emit_value(buffer),
3640
Self::Other(o) => o.emit_value(buffer),
3741
}
3842
}
@@ -41,6 +45,7 @@ impl nla::Nla for TcOpt {
4145
match self {
4246
Self::Ingress => unreachable!(),
4347
Self::U32(u) => u.kind(),
48+
Self::Matchall(m) => m.kind(),
4449
Self::Other(o) => o.kind(),
4550
}
4651
}
@@ -60,6 +65,10 @@ where
6065
u32::KIND => Self::U32(
6166
u32::Nla::parse(buf).context("failed to parse u32 nlas")?,
6267
),
68+
matchall::KIND => Self::Matchall(
69+
matchall::Nla::parse(buf)
70+
.context("failed to parse matchall nlas")?,
71+
),
6372
_ => Self::Other(DefaultNla::parse(buf)?),
6473
})
6574
}

0 commit comments

Comments
 (0)