Skip to content
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

Add more parsing to tc module #75

Merged
merged 10 commits into from
Dec 5, 2023
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,21 @@ crate directly.
changed netlink attribute. To capture the netlink raw bytes, you may use
tcpdump/wireshark again the `nlmon` interface. For example:

* The integration test(play with linux kernel netlink interface) should be
placed into `rtnetlink` crate. Current(netlink-packet-route) crate should
only unit test case only.

```bash
modprobe nlmon
ip link add nl0 type nlmon
ip link set nl0 up
tcpdump -i nl0 -w netlink_capture_file.cap
# Then use wireshark to open this `netlink_capture_file.cap`
# Find out the packet you are interested,
# right click -> "Copy" -> "...as Hex Dump".
# You may use https://github.com/cathay4t/hex_to_rust to convert this
# hexdump to rust u8 array
```
* The integration test(play with linux kernel netlink interface) should be
placed into `rtnetlink` crate. Current(netlink-packet-route) crate should
only unit test case only.


* For certain netlink message which cannot captured by nlmon, please use
Rust Debug and explain every bits in comment.
Expand Down
4 changes: 4 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* Only tc has unparsed `Vec<u8>` left.
* Still has many flags not converted into `Vec<enum>`.
* Many place holders in `link::InfoData`.
* Missing unit test cases.
2 changes: 1 addition & 1 deletion src/link/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub struct LinkHeader {
/// Link index.
pub index: u32,
/// Link type. It should be set to one of the `ARPHRD_*`
/// constants. The most common value is [ALinkLayerType::ETHER] for
/// constants. The most common value is [LinkLayerType::Ether] for
/// Ethernet.
/// The LinkLayerType has `From<u16>` and `From<LinkLayerType> for u16`
/// implemented.
Expand Down
2 changes: 0 additions & 2 deletions src/route/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ const RTM_F_OFFLOAD: u32 = 0x4000;
const RTM_F_TRAP: u32 = 0x8000;
const RTM_F_OFFLOAD_FAILED: u32 = 0x20000000;

/// Flags that can be set in a `RTM_GETROUTE`
/// ([`RouteNetlinkMessage::GetRoute`]) message.
#[derive(Clone, Eq, PartialEq, Debug, Copy)]
#[non_exhaustive]
pub enum RouteFlag {
Expand Down
4 changes: 2 additions & 2 deletions src/route/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ impl<'a, T: AsRef<[u8]> + ?Sized> RouteMessageBuffer<&'a T> {
/// messages headers.
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct RouteHeader {
/// Address family of the route: either [AddressFamily::Ipv4] for IPv4,
/// or [AddressFamily::Ipv6] for IPv6.
/// Address family of the route: either [AddressFamily::Inet] for IPv4,
/// or [AddressFamily::Inet6] for IPv6.
pub address_family: AddressFamily,
/// Prefix length of the destination subnet.
pub destination_prefix_length: u8,
Expand Down
2 changes: 1 addition & 1 deletion src/rule/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub enum RuleAttribute {
Source(IpAddr),
/// input interface name
Iifname(String),
/// The priority number of another rule for [RuleAction::Goto]
/// The priority number of another rule for [super::RuleAction::Goto]
Goto(u32),
Priority(u32),
FwMark(u32),
Expand Down
2 changes: 0 additions & 2 deletions src/rule/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ const FIB_RULE_IIF_DETACHED: u32 = 0x00000008;
const FIB_RULE_DEV_DETACHED: u32 = FIB_RULE_IIF_DETACHED;
const FIB_RULE_OIF_DETACHED: u32 = 0x00000010;

/// Flags that can be set in a `RTM_GETROUTE`
/// ([`RuleNetlinkMessage::GetRule`]) message.
#[derive(Clone, Eq, PartialEq, Debug, Copy)]
#[non_exhaustive]
pub enum RuleFlag {
Expand Down
70 changes: 67 additions & 3 deletions src/tc/actions/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@
pub struct TcActionGeneric {
pub index: u32,
pub capab: u32,
pub action: i32,
pub action: TcActionType,
pub refcnt: i32,
pub bindcnt: i32,
}
Expand All @@ -267,7 +267,7 @@
let mut packet = TcActionGenericBuffer::new(buffer);
packet.set_index(self.index);
packet.set_capab(self.capab);
packet.set_action(self.action);
packet.set_action(self.action.into());
packet.set_refcnt(self.refcnt);
packet.set_bindcnt(self.bindcnt);
}
Expand All @@ -278,9 +278,73 @@
Ok(Self {
index: buf.index(),
capab: buf.capab(),
action: buf.action(),
action: buf.action().into(),
refcnt: buf.refcnt(),
bindcnt: buf.bindcnt(),
})
}
}

const TC_ACT_UNSPEC: i32 = -1;
const TC_ACT_OK: i32 = 0;
const TC_ACT_RECLASSIFY: i32 = 1;
const TC_ACT_SHOT: i32 = 2;
const TC_ACT_PIPE: i32 = 3;
const TC_ACT_STOLEN: i32 = 4;
const TC_ACT_QUEUED: i32 = 5;
const TC_ACT_REPEAT: i32 = 6;
const TC_ACT_REDIRECT: i32 = 7;
const TC_ACT_TRAP: i32 = 8;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
#[non_exhaustive]
pub enum TcActionType {
#[default]
Unspec,
Ok,
Reclassify,
Shot,
Pipe,
Stolen,
Queued,
Repeat,
Redirect,
Trap,
Other(i32),
}

impl From<i32> for TcActionType {
fn from(d: i32) -> Self {
match d {
TC_ACT_UNSPEC => Self::Unspec,

Check warning on line 319 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L319

Added line #L319 was not covered by tests
TC_ACT_OK => Self::Ok,
TC_ACT_RECLASSIFY => Self::Reclassify,
TC_ACT_SHOT => Self::Shot,

Check warning on line 322 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L321-L322

Added lines #L321 - L322 were not covered by tests
TC_ACT_PIPE => Self::Pipe,
TC_ACT_STOLEN => Self::Stolen,
TC_ACT_QUEUED => Self::Queued,
TC_ACT_REPEAT => Self::Repeat,
TC_ACT_REDIRECT => Self::Redirect,
TC_ACT_TRAP => Self::Trap,
_ => Self::Other(d),

Check warning on line 329 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L324-L329

Added lines #L324 - L329 were not covered by tests
}
}
}

impl From<TcActionType> for i32 {
fn from(v: TcActionType) -> i32 {
match v {
TcActionType::Unspec => TC_ACT_UNSPEC,

Check warning on line 337 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L337

Added line #L337 was not covered by tests
TcActionType::Ok => TC_ACT_OK,
TcActionType::Reclassify => TC_ACT_RECLASSIFY,
TcActionType::Shot => TC_ACT_SHOT,

Check warning on line 340 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L339-L340

Added lines #L339 - L340 were not covered by tests
TcActionType::Pipe => TC_ACT_PIPE,
TcActionType::Stolen => TC_ACT_STOLEN,
TcActionType::Queued => TC_ACT_QUEUED,
TcActionType::Repeat => TC_ACT_REPEAT,
TcActionType::Redirect => TC_ACT_REDIRECT,
TcActionType::Trap => TC_ACT_TRAP,
TcActionType::Other(d) => d,

Check warning on line 347 in src/tc/actions/action.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/action.rs#L342-L347

Added lines #L342 - L347 were not covered by tests
}
}
}
46 changes: 43 additions & 3 deletions src/tc/actions/mirror.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
#[non_exhaustive]
pub struct TcMirror {
pub generic: TcActionGeneric,
pub eaction: i32,
pub eaction: TcMirrorActionType,
pub ifindex: u32,
}

Expand All @@ -97,7 +97,7 @@
fn emit(&self, buffer: &mut [u8]) {
let mut packet = TcMirrorBuffer::new(buffer);
self.generic.emit(packet.generic_mut());
packet.set_eaction(self.eaction);
packet.set_eaction(self.eaction.into());
packet.set_ifindex(self.ifindex);
}
}
Expand All @@ -110,8 +110,48 @@
generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(
buf.generic(),
))?,
eaction: buf.eaction(),
eaction: buf.eaction().into(),
ifindex: buf.ifindex(),
})
}
}

const TCA_EGRESS_REDIR: i32 = 1;
const TCA_EGRESS_MIRROR: i32 = 2;
const TCA_INGRESS_REDIR: i32 = 3;
const TCA_INGRESS_MIRROR: i32 = 4;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
#[non_exhaustive]
pub enum TcMirrorActionType {
#[default]
EgressRedir,
EgressMirror,
IngressRedir,
IngressMirror,
Other(i32),
}

impl From<i32> for TcMirrorActionType {
fn from(d: i32) -> Self {
match d {
TCA_EGRESS_REDIR => Self::EgressRedir,

Check warning on line 138 in src/tc/actions/mirror.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/mirror.rs#L138

Added line #L138 was not covered by tests
TCA_EGRESS_MIRROR => Self::EgressMirror,
TCA_INGRESS_REDIR => Self::IngressRedir,
TCA_INGRESS_MIRROR => Self::IngressMirror,
_ => Self::Other(d),

Check warning on line 142 in src/tc/actions/mirror.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/mirror.rs#L140-L142

Added lines #L140 - L142 were not covered by tests
}
}
}

impl From<TcMirrorActionType> for i32 {
fn from(v: TcMirrorActionType) -> i32 {
match v {
TcMirrorActionType::EgressRedir => TCA_EGRESS_REDIR,

Check warning on line 150 in src/tc/actions/mirror.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/mirror.rs#L150

Added line #L150 was not covered by tests
TcMirrorActionType::EgressMirror => TCA_EGRESS_MIRROR,
TcMirrorActionType::IngressRedir => TCA_INGRESS_REDIR,
TcMirrorActionType::IngressMirror => TCA_INGRESS_MIRROR,
TcMirrorActionType::Other(d) => d,

Check warning on line 154 in src/tc/actions/mirror.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/mirror.rs#L152-L154

Added lines #L152 - L154 were not covered by tests
}
}
}
7 changes: 5 additions & 2 deletions src/tc/actions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
mod action;
mod mirror;
mod nat;
pub(crate) mod nat_flag;

pub use self::action::{
TcAction, TcActionAttribute, TcActionGeneric, TcActionGenericBuffer,
TcActionOption,
TcActionOption, TcActionType,
};
pub use self::mirror::{
TcActionMirror, TcActionMirrorOption, TcMirror, TcMirrorBuffer,
TcActionMirror, TcActionMirrorOption, TcMirror, TcMirrorActionType,
TcMirrorBuffer,
};
pub use self::nat::{TcActionNat, TcActionNatOption, TcNat, TcNatBuffer};
pub use self::nat_flag::TcNatFlag;
22 changes: 8 additions & 14 deletions src/tc/actions/nat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
DecodeError,
};

use super::{TcActionGeneric, TcActionGenericBuffer};
use super::{
nat_flag::VecTcNatFlag, TcActionGeneric, TcActionGenericBuffer, TcNatFlag,
};

const TCA_NAT_PARMS: u16 = 1;
const TCA_NAT_TM: u16 = 2;
Expand Down Expand Up @@ -73,16 +75,15 @@
}

const TC_NAT_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 16;
const TCA_NAT_FLAG_EGRESS: u32 = 1;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub struct TcNat {
pub generic: TcActionGeneric,
pub old_addr: Ipv4Addr,
pub new_addr: Ipv4Addr,
pub mask: Ipv4Addr,
pub flags: u32, // TODO(Gris Ge): should a Vec<enum TcNatFlag>
pub flags: Vec<TcNatFlag>,
}

impl Default for TcNat {
Expand All @@ -92,7 +93,7 @@
old_addr: Ipv4Addr::UNSPECIFIED,
new_addr: Ipv4Addr::UNSPECIFIED,
mask: Ipv4Addr::UNSPECIFIED,
flags: 0,
flags: vec![],

Check warning on line 96 in src/tc/actions/nat.rs

View check run for this annotation

Codecov / codecov/patch

src/tc/actions/nat.rs#L96

Added line #L96 was not covered by tests
}
}
}
Expand All @@ -105,13 +106,6 @@
flags: (u32, (TcActionGeneric::BUF_LEN+12)..TC_NAT_BUF_LEN),
});

impl TcNat {
pub fn egress(mut self) -> Self {
self.flags = TCA_NAT_FLAG_EGRESS;
self
}
}

impl Emitable for TcNat {
fn buffer_len(&self) -> usize {
TC_NAT_BUF_LEN
Expand All @@ -127,7 +121,7 @@
.new_addr_mut()
.copy_from_slice(&self.new_addr.octets());
packet.mask_mut().copy_from_slice(&self.mask.octets());
packet.set_flags(self.flags);
packet.set_flags(u32::from(&VecTcNatFlag(self.flags.to_vec())));
}
}

Expand All @@ -140,7 +134,7 @@
old_addr: parse_ipv4(buf.old_addr())?,
new_addr: parse_ipv4(buf.new_addr())?,
mask: parse_ipv4(buf.mask())?,
flags: buf.flags(),
flags: VecTcNatFlag::from(buf.flags()).0,
})
}
}
Expand Down
Loading