Skip to content

Re #21 - Add matchall filter type #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/rtnl/tc/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ pub const TC_H_MIN_PRIORITY: u32 = 0xFFE0;
pub const TC_H_MIN_INGRESS: u32 = 0xFFF2;
pub const TC_H_MIN_EGRESS: u32 = 0xFFF3;

// matchall filters
pub const TCA_MATCHALL_UNSPEC: u16 = 0;
pub const TCA_MATCHALL_CLASSID: u16 = 1;
pub const TCA_MATCHALL_ACT: u16 = 2;
pub const TCA_MATCHALL_FLAGS: u16 = 3;
pub const TCA_MATCHALL_PCNT: u16 = 4;

/// U32 filters
pub const TCA_U32_UNSPEC: u16 = 0;
pub const TCA_U32_CLASSID: u16 = 1;
Expand Down
94 changes: 94 additions & 0 deletions src/rtnl/tc/nlas/filter/matchall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: MIT

/// Matchall filter
///
/// Matches all packets and performs an action on them.
use anyhow::Context;
use byteorder::{ByteOrder, NativeEndian};
use netlink_packet_utils::{
nla::{self, DefaultNla, NlaBuffer, NlasIterator},
parsers::parse_u32,
traits::{Emitable, Parseable},
DecodeError,
};

use crate::tc::{constants::*, Action};
pub const KIND: &str = "matchall";

#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub enum Nla {
Unspec(Vec<u8>),
ClassId(u32),
Act(Vec<Action>),
Pcnt(Vec<u8>),
Flags(u32),
Other(DefaultNla),
}

impl nla::Nla for Nla {
fn value_len(&self) -> usize {
use self::Nla::*;
match self {
Unspec(b) | Pcnt(b) => b.len(),
ClassId(_) | Flags(_) => 4,
Act(acts) => acts.as_slice().buffer_len(),
Other(attr) => attr.value_len(),
}
}

fn emit_value(&self, buffer: &mut [u8]) {
use self::Nla::*;
match self {
Unspec(b) | Pcnt(b) => buffer.copy_from_slice(b.as_slice()),
ClassId(i) | Flags(i) => NativeEndian::write_u32(buffer, *i),
Act(acts) => acts.as_slice().emit(buffer),
Other(attr) => attr.emit_value(buffer),
}
}

fn kind(&self) -> u16 {
use self::Nla::*;
match self {
Unspec(_) => TCA_MATCHALL_UNSPEC,
ClassId(_) => TCA_MATCHALL_CLASSID,
Act(_) => TCA_MATCHALL_ACT,
Pcnt(_) => TCA_MATCHALL_PCNT,
Flags(_) => TCA_MATCHALL_FLAGS,
Other(attr) => attr.kind(),
}
}
}

impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for Nla {
fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
use self::Nla::*;
let payload = buf.value();
Ok(match buf.kind() {
TCA_MATCHALL_UNSPEC => Unspec(payload.to_vec()),
TCA_MATCHALL_CLASSID => ClassId(
parse_u32(payload)
.context("failed to parse TCA_MATCHALL_UNSPEC")?,
),
TCA_MATCHALL_ACT => {
let mut acts = vec![];
for act in NlasIterator::new(payload) {
let act = act.context("invalid TCA_MATCHALL_ACT")?;
acts.push(
Action::parse(&act)
.context("failed to parse TCA_MATCHALL_ACT")?,
);
}
Act(acts)
}
TCA_MATCHALL_PCNT => Pcnt(payload.to_vec()),
TCA_MATCHALL_FLAGS => Flags(
parse_u32(payload)
.context("failed to parse TCA_MATCHALL_FLAGS")?,
),
_ => Other(
DefaultNla::parse(buf).context("failed to parse u32 nla")?,
),
})
}
}
1 change: 1 addition & 0 deletions src/rtnl/tc/nlas/filter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: MIT

pub mod matchall;
pub mod u32;
11 changes: 10 additions & 1 deletion src/rtnl/tc/nlas/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use netlink_packet_utils::{
DecodeError,
};

use crate::tc::{ingress, u32};
use crate::tc::{ingress, matchall, u32};

#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
Expand All @@ -16,6 +16,8 @@ pub enum TcOpt {
Ingress,
// Filter specific options
U32(u32::Nla),
// matchall options
Matchall(matchall::Nla),
// Other options
Other(DefaultNla),
}
Expand All @@ -25,6 +27,7 @@ impl nla::Nla for TcOpt {
match self {
Self::Ingress => 0,
Self::U32(u) => u.value_len(),
Self::Matchall(m) => m.value_len(),
Self::Other(o) => o.value_len(),
}
}
Expand All @@ -33,6 +36,7 @@ impl nla::Nla for TcOpt {
match self {
Self::Ingress => unreachable!(),
Self::U32(u) => u.emit_value(buffer),
Self::Matchall(m) => m.emit_value(buffer),
Self::Other(o) => o.emit_value(buffer),
}
}
Expand All @@ -41,6 +45,7 @@ impl nla::Nla for TcOpt {
match self {
Self::Ingress => unreachable!(),
Self::U32(u) => u.kind(),
Self::Matchall(m) => m.kind(),
Self::Other(o) => o.kind(),
}
}
Expand All @@ -60,6 +65,10 @@ where
u32::KIND => Self::U32(
u32::Nla::parse(buf).context("failed to parse u32 nlas")?,
),
matchall::KIND => Self::Matchall(
matchall::Nla::parse(buf)
.context("failed to parse matchall nlas")?,
),
_ => Self::Other(DefaultNla::parse(buf)?),
})
}
Expand Down