Skip to content

Commit

Permalink
Re rust-netlink#21 - Add matchall filter type
Browse files Browse the repository at this point in the history
This tc filter matches all packets that encounter it.
  • Loading branch information
Erich Heine committed Feb 16, 2023
1 parent 75ce74c commit bcddc75
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/rtnl/tc/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ 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;
pub const TCA_MATCHALL_PAD: u16 = 5;
pub const TCA_MATCHALL_MAX: u16 = TCA_MATCHALL_PAD;

/// 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

0 comments on commit bcddc75

Please sign in to comment.