Skip to content

Commit 68a956d

Browse files
author
Erich Heine
committed
Re #21 - Add matchall filter type
This tc filter matches all packets that encounter it.
1 parent 4605b65 commit 68a956d

File tree

4 files changed

+116
-1
lines changed

4 files changed

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

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

33
pub mod u32;
4+
pub mod matchall;

src/rtnl/tc/nlas/options.rs

Lines changed: 9 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, u32, matchall};
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,9 @@ 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).context("failed to parse matchall nlas")?,
70+
),
6371
_ => Self::Other(DefaultNla::parse(buf)?),
6472
})
6573
}

0 commit comments

Comments
 (0)