Skip to content

Commit 00a06ea

Browse files
committed
Support for tc-flower
1 parent baed9af commit 00a06ea

25 files changed

+5420
-38
lines changed

Diff for: Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ name = "dump_packet_links"
2929
[dev-dependencies]
3030
netlink-sys = { version = "0.8.5" }
3131
pretty_assertions = "0.7.2"
32+
hex = "0.4.3"

Diff for: src/enc.rs

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use netlink_packet_utils::DecodeError;
2+
3+
/// An identifier for an encapsulation key used by a tunnel.
4+
///
5+
/// Examples include a VNIs for VXLAN and Geneve tunnels, ERSPAN/GRE keys, and
6+
/// GTP tunnel keys.
7+
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
8+
#[repr(transparent)]
9+
pub struct EncKeyId(u32);
10+
11+
impl EncKeyId {
12+
/// Create a new `EncKeyId` without checking the validity of the ID value.
13+
///
14+
/// # Safety
15+
///
16+
/// Failure to ensure the ID is within the valid range for the tunnel in
17+
/// question may lead to semantically invalid netlink messages.
18+
///
19+
/// If you know the tunnel type (e.g., vxlan) and wish to confirm that the
20+
/// ID is within the valid range of values for that tunnel type, use the
21+
/// corresponding new method (e.g., `new_vxlan_vni`).
22+
#[must_use]
23+
pub const fn new_unchecked(id: u32) -> Self {
24+
Self(id)
25+
}
26+
27+
/// Create a new `EncKeyId` and confirm that it is within the valid range
28+
/// of vxlan vni values.
29+
///
30+
/// # Errors
31+
/// Returns an error if the ID is zero or greater than or equal to 2^24.
32+
pub fn new_vxlan_vni(id: u32) -> Result<Self, DecodeError> {
33+
crate::net::vxlan::Vni::new(id).map(Into::into)
34+
}
35+
36+
/// Create a new `EncKeyId` and confirm that it is within the valid range
37+
/// of geneve vni values.
38+
///
39+
/// # Errors
40+
///
41+
/// Returns an error if the ID is greater than or equal to 2^24.
42+
pub fn new_geneve_vni(id: u32) -> Result<Self, DecodeError> {
43+
match Self::new_nbit::<24>(id) {
44+
Ok(id) => Ok(id),
45+
Err(_) => Err(DecodeError::from(
46+
"Geneve VNI must be less than 2^24, received {id}",
47+
)),
48+
}
49+
}
50+
51+
/// Create a new `EncKeyId` in the space of valid GRE keys.
52+
///
53+
/// # Safety
54+
///
55+
/// Since GRE keys are 32 bits and all values are legal, this method is not
56+
/// failable.
57+
#[must_use]
58+
pub fn new_gre_key(id: u32) -> Self {
59+
Self(id)
60+
}
61+
62+
/// Create a new `EncKeyId` and confirm that it is within the valid range
63+
/// of gtp tunnel key values.
64+
///
65+
/// # Errors
66+
///
67+
/// Returns an error if the ID is zero.
68+
pub fn new_gtp_key(id: u32) -> Result<Self, DecodeError> {
69+
if id == 0 {
70+
return Err(DecodeError::from(
71+
"zero is not a legal GTP tunnel key",
72+
));
73+
}
74+
Ok(Self(id))
75+
}
76+
77+
/// Create a new `EncKeyId` and confirm that it is within the valid range
78+
/// of N bit values.
79+
///
80+
/// # Errors
81+
///
82+
/// Returns an error if the ID is greater than or equal to 2^N.
83+
const fn new_nbit<const N: usize>(id: u32) -> Result<Self, KeyTooLarge> {
84+
if id >= (1 << N) {
85+
return Err(KeyTooLarge);
86+
};
87+
Ok(Self(id))
88+
}
89+
}
90+
91+
impl From<EncKeyId> for u32 {
92+
fn from(id: EncKeyId) -> u32 {
93+
id.0
94+
}
95+
}
96+
97+
impl AsRef<u32> for EncKeyId {
98+
fn as_ref(&self) -> &u32 {
99+
&self.0
100+
}
101+
}
102+
103+
impl From<u32> for EncKeyId {
104+
/// Convert `u32` to an `EncKeyId`.
105+
///
106+
/// # Safety
107+
///
108+
/// This conversion is infallible but may produce a semantically invalid key
109+
/// depending on the tunnel type.
110+
///
111+
/// If you know the tunnel type (e.g., vxlan) and wish to confirm that the
112+
/// ID is within the valid range of values for that tunnel type, use the
113+
/// corresponding "new" method on the `EncKeyId` type (e.g.,
114+
/// `EncKeyId::new_vxlan_vni`).
115+
fn from(id: u32) -> Self {
116+
Self(id)
117+
}
118+
}
119+
120+
#[derive(Debug)]
121+
#[must_use]
122+
struct KeyTooLarge;
123+
124+
impl From<crate::net::vxlan::Vni> for EncKeyId {
125+
fn from(vni: crate::net::vxlan::Vni) -> Self {
126+
Self(vni.into())
127+
}
128+
}

Diff for: src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,22 @@ mod address_family_linux;
2121
#[cfg(any(target_os = "linux", target_os = "fuchsia"))]
2222
pub use self::address_family_linux::AddressFamily;
2323

24+
mod enc;
25+
pub use self::enc::*;
26+
2427
#[cfg(target_os = "freebsd")]
2528
mod address_family_freebsd;
2629
#[cfg(target_os = "freebsd")]
2730
pub use self::address_family_freebsd::AddressFamily;
31+
pub mod net;
2832

2933
#[cfg(not(any(
3034
target_os = "linux",
3135
target_os = "fuchsia",
3236
target_os = "freebsd",
3337
)))]
3438
mod address_family_fallback;
39+
3540
#[cfg(not(any(
3641
target_os = "linux",
3742
target_os = "fuchsia",

Diff for: src/message.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// SPDX-License-Identifier: MIT
22

33
use anyhow::Context;
4-
use netlink_packet_utils::{
5-
DecodeError, Emitable, Parseable, ParseableParametrized,
6-
};
7-
84
use netlink_packet_core::{
95
NetlinkDeserializable, NetlinkHeader, NetlinkPayload, NetlinkSerializable,
106
};
7+
use netlink_packet_utils::{
8+
DecodeError, Emitable, Parseable, ParseableParametrized,
9+
};
1110

11+
use crate::tc::{TcMessage, TcMessageBuffer};
1212
use crate::{
1313
address::{AddressHeader, AddressMessage, AddressMessageBuffer},
1414
link::{LinkMessage, LinkMessageBuffer},
@@ -18,7 +18,6 @@ use crate::{
1818
prefix::{PrefixMessage, PrefixMessageBuffer},
1919
route::{RouteHeader, RouteMessage, RouteMessageBuffer},
2020
rule::{RuleMessage, RuleMessageBuffer},
21-
tc::{TcMessage, TcMessageBuffer},
2221
};
2322

2423
const RTM_NEWLINK: u16 = 16;
@@ -46,9 +45,9 @@ const RTM_GETTCLASS: u16 = 42;
4645
const RTM_NEWTFILTER: u16 = 44;
4746
const RTM_DELTFILTER: u16 = 45;
4847
const RTM_GETTFILTER: u16 = 46;
49-
// const RTM_NEWACTION: u16 = 48;
50-
// const RTM_DELACTION: u16 = 49;
51-
// const RTM_GETACTION: u16 = 50;
48+
const RTM_NEWACTION: u16 = 48;
49+
const RTM_DELACTION: u16 = 49;
50+
const RTM_GETACTION: u16 = 50;
5251
const RTM_NEWPREFIX: u16 = 52;
5352
// const RTM_GETMULTICAST: u16 = 58;
5453
// const RTM_GETANYCAST: u16 = 62;

Diff for: src/net/arp.rs

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
const RESERVED: u8 = 0;
2+
const REQUEST: u8 = 1;
3+
const REPLY: u8 = 2;
4+
const REQUEST_REVERSE: u8 = 3;
5+
const REPLY_REVERSE: u8 = 4;
6+
const DRARP_REQUEST: u8 = 5;
7+
const DRARP_REPLY: u8 = 6;
8+
const DRARP_ERROR: u8 = 7;
9+
const IN_ARP_REQUEST: u8 = 8;
10+
const IN_ARP_REPLY: u8 = 9;
11+
const ARP_NAK: u8 = 10;
12+
const MARS_REQUEST: u8 = 11;
13+
const MARS_MULTI: u8 = 12;
14+
const MARS_MSERV: u8 = 13;
15+
const MARS_JOIN: u8 = 14;
16+
const MARS_LEAVE: u8 = 15;
17+
const MARS_NAK: u8 = 16;
18+
const MARS_UNSERV: u8 = 17;
19+
const MARS_SJOIN: u8 = 18;
20+
const MARS_SLEAVE: u8 = 19;
21+
const MARS_GROUP_LIST_REQUEST: u8 = 20;
22+
const MARS_GROUP_LIST_REPLY: u8 = 21;
23+
const MARS_REDIRECT_MAP: u8 = 22;
24+
const MAPO_SUNARP: u8 = 23;
25+
const OP_EXP1: u8 = 24;
26+
const OP_EXP2: u8 = 25;
27+
28+
/// Enum of ARP operation codes.
29+
///
30+
/// List from [iana.org][1]
31+
///
32+
/// [1]: https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
33+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Ord, PartialOrd, Hash)]
34+
#[non_exhaustive]
35+
#[repr(u8)]
36+
pub enum Operation {
37+
Reserved = RESERVED,
38+
Request = REQUEST,
39+
Reply = REPLY,
40+
RequestReverse = REQUEST_REVERSE,
41+
ReplyReverse = REPLY_REVERSE,
42+
DrarpRequest = DRARP_REQUEST,
43+
DrarpReply = DRARP_REPLY,
44+
DrarpError = DRARP_ERROR,
45+
InArpRequest = IN_ARP_REQUEST,
46+
InArpReply = IN_ARP_REPLY,
47+
ArpNak = ARP_NAK,
48+
MarsRequest = MARS_REQUEST,
49+
MarsMulti = MARS_MULTI,
50+
MarsMServ = MARS_MSERV,
51+
MarsJoin = MARS_JOIN,
52+
MarsLeave = MARS_LEAVE,
53+
MarsNAK = MARS_NAK,
54+
MarsUnserv = MARS_UNSERV,
55+
MarsSJoin = MARS_SJOIN,
56+
MarsSLeave = MARS_SLEAVE,
57+
MarsGroupListRequest = MARS_GROUP_LIST_REQUEST,
58+
MarsGroupListReply = MARS_GROUP_LIST_REPLY,
59+
MarsRedirectMap = MARS_REDIRECT_MAP,
60+
MapoSUnarp = MAPO_SUNARP,
61+
OpExp1 = OP_EXP1,
62+
OpExp2 = OP_EXP2,
63+
Other(u8),
64+
}
65+
66+
impl AsRef<u8> for Operation {
67+
fn as_ref(&self) -> &u8 {
68+
match self {
69+
Operation::Reserved => &RESERVED,
70+
Operation::Request => &REQUEST,
71+
Operation::Reply => &REPLY,
72+
Operation::RequestReverse => &REQUEST_REVERSE,
73+
Operation::ReplyReverse => &REPLY_REVERSE,
74+
Operation::DrarpRequest => &DRARP_REQUEST,
75+
Operation::DrarpReply => &DRARP_REPLY,
76+
Operation::DrarpError => &DRARP_ERROR,
77+
Operation::InArpRequest => &IN_ARP_REQUEST,
78+
Operation::InArpReply => &IN_ARP_REPLY,
79+
Operation::ArpNak => &ARP_NAK,
80+
Operation::MarsRequest => &MARS_REQUEST,
81+
Operation::MarsMulti => &MARS_MULTI,
82+
Operation::MarsMServ => &MARS_MSERV,
83+
Operation::MarsJoin => &MARS_JOIN,
84+
Operation::MarsLeave => &MARS_LEAVE,
85+
Operation::MarsNAK => &MARS_NAK,
86+
Operation::MarsUnserv => &MARS_UNSERV,
87+
Operation::MarsSJoin => &MARS_SJOIN,
88+
Operation::MarsSLeave => &MARS_SLEAVE,
89+
Operation::MarsGroupListRequest => &MARS_GROUP_LIST_REQUEST,
90+
Operation::MarsGroupListReply => &MARS_GROUP_LIST_REPLY,
91+
Operation::MarsRedirectMap => &MARS_REDIRECT_MAP,
92+
Operation::MapoSUnarp => &MAPO_SUNARP,
93+
Operation::OpExp1 => &OP_EXP1,
94+
Operation::OpExp2 => &OP_EXP2,
95+
Operation::Other(x) => x,
96+
}
97+
}
98+
}
99+
100+
impl From<u8> for Operation {
101+
fn from(value: u8) -> Self {
102+
match value {
103+
RESERVED => Operation::Reserved,
104+
REQUEST => Operation::Request,
105+
REPLY => Operation::Reply,
106+
REQUEST_REVERSE => Operation::RequestReverse,
107+
REPLY_REVERSE => Operation::ReplyReverse,
108+
DRARP_REQUEST => Operation::DrarpRequest,
109+
DRARP_REPLY => Operation::DrarpReply,
110+
DRARP_ERROR => Operation::DrarpError,
111+
IN_ARP_REQUEST => Operation::InArpRequest,
112+
IN_ARP_REPLY => Operation::InArpReply,
113+
ARP_NAK => Operation::ArpNak,
114+
MARS_REQUEST => Operation::MarsRequest,
115+
MARS_MULTI => Operation::MarsMulti,
116+
MARS_MSERV => Operation::MarsMServ,
117+
MARS_JOIN => Operation::MarsJoin,
118+
MARS_LEAVE => Operation::MarsLeave,
119+
MARS_NAK => Operation::MarsNAK,
120+
MARS_UNSERV => Operation::MarsUnserv,
121+
MARS_SJOIN => Operation::MarsSJoin,
122+
MARS_SLEAVE => Operation::MarsSLeave,
123+
MARS_GROUP_LIST_REQUEST => Operation::MarsGroupListRequest,
124+
MARS_GROUP_LIST_REPLY => Operation::MarsGroupListReply,
125+
MARS_REDIRECT_MAP => Operation::MarsRedirectMap,
126+
MAPO_SUNARP => Operation::MapoSUnarp,
127+
OP_EXP1 => Operation::OpExp1,
128+
OP_EXP2 => Operation::OpExp2,
129+
x => Operation::Other(x),
130+
}
131+
}
132+
}
133+
134+
impl From<Operation> for u8 {
135+
fn from(value: Operation) -> Self {
136+
*value.as_ref()
137+
}
138+
}

0 commit comments

Comments
 (0)