Skip to content

Commit

Permalink
Merge pull request #76 from thearossman/main
Browse files Browse the repository at this point in the history
Add PacketList Datatypes
  • Loading branch information
thearossman authored Dec 2, 2024
2 parents 6ea7f1d + 2543af9 commit 5598165
Show file tree
Hide file tree
Showing 11 changed files with 498 additions and 41 deletions.
6 changes: 4 additions & 2 deletions core/src/conntrack/conn/conn_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::protocols::stream::{
ConnData, ParseResult, ParserRegistry, ParsingState, ProbeRegistryResult,
};
use crate::subscription::{Subscription, Trackable};
use crate::FiveTuple;
use crate::{FiveTuple, Mbuf};

#[derive(Debug)]
pub(crate) struct ConnInfo<T>
Expand Down Expand Up @@ -77,7 +77,9 @@ where
}
if self.actions.buffer_frame() {
// Track frame for (potential) future delivery
self.sdata.track_packet(pdu.mbuf_own());
// Used when a filter has partially matched for a
// subscription that requests packets
self.sdata.track_packet(Mbuf::new_ref(pdu.mbuf_ref()));
}
}

Expand Down
5 changes: 3 additions & 2 deletions core/src/conntrack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ where
};
if let Ok(mut conn) = conn {
conn.info.filter_first_packet(&pdu, subscription);
if !conn.info.actions.drop() {
conn.info.consume_pdu(pdu, subscription, &self.registry);
if conn.info.actions.update_pdu() {
conn.info.sdata.update(&pdu, false);
}
conn.info.consume_pdu(pdu, subscription, &self.registry);
if !conn.remove_from_table() {
self.timerwheel.insert(
&conn_id,
Expand Down
4 changes: 4 additions & 0 deletions core/src/dpdk/inlined.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ uint16_t rte_mbuf_refcnt_update_(struct rte_mbuf* m, int16_t value) {
return rte_mbuf_refcnt_update(m, value);
}

void rte_mbuf_refcnt_set_(struct rte_mbuf* m, int16_t value) {
return rte_mbuf_refcnt_set(m, value);
}

char* rte_pktmbuf_adj_(struct rte_mbuf* m, uint16_t len) {
return rte_pktmbuf_adj(m, len);
}
Expand Down
6 changes: 6 additions & 0 deletions core/src/dpdk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern "C" {
) -> u16;
fn rte_mbuf_refcnt_read_(m: *const rte_mbuf) -> u16;
fn rte_mbuf_refcnt_update_(m: *mut rte_mbuf, value: i16) -> u16;
fn rte_mbuf_refcnt_set_(m: *mut rte_mbuf, value: i16);
fn rte_pktmbuf_adj_(packet: *mut rte_mbuf, len: u16) -> *mut c_char;
fn rte_pktmbuf_trim_(packet: *mut rte_mbuf, len: u16) -> c_int;
fn rte_lcore_id_() -> u16;
Expand Down Expand Up @@ -105,6 +106,11 @@ pub unsafe fn rte_mbuf_refcnt_update(m: *mut rte_mbuf, value: i16) -> u16 {
rte_mbuf_refcnt_update_(m, value)
}

#[inline]
pub unsafe fn rte_mbuf_refcnt_set(m: *mut rte_mbuf, value: i16) {
rte_mbuf_refcnt_set_(m, value)
}

#[inline]
pub unsafe fn rte_pktmbuf_adj(packet: *mut rte_mbuf, len: u16) -> *mut c_char {
rte_pktmbuf_adj_(packet, len)
Expand Down
30 changes: 12 additions & 18 deletions core/src/filter/datatypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ pub struct DataType {
pub needs_update: bool,
/// True if the datatype requires invoking `update` method after reassembly
pub needs_update_reassembled: bool,
/// True if the datatype requires the framework to buffer matched packets
pub track_packets: bool,
/// A vector of the application-layer parsers required by this datatype
/// Retina loads the union of parsers required by all datatypes and filters
pub stream_protos: Vec<&'static str>,
Expand All @@ -76,7 +74,6 @@ impl DataType {
track_sessions: false,
needs_update: true,
needs_update_reassembled: false,
track_packets: false,
stream_protos: vec![],
as_str,
}
Expand All @@ -91,7 +88,6 @@ impl DataType {
track_sessions: false,
needs_update: false,
needs_update_reassembled: false,
track_packets: false,
stream_protos,
as_str,
}
Expand All @@ -106,7 +102,6 @@ impl DataType {
track_sessions: false,
needs_update: false,
needs_update_reassembled: false,
track_packets: false,
stream_protos: vec![],
as_str,
}
Expand All @@ -121,7 +116,18 @@ impl DataType {
track_sessions: false,
needs_update: false,
needs_update_reassembled: false,
track_packets: false,
stream_protos: vec![],
as_str,
}
}

pub fn new_default_pktlist(as_str: &'static str, reassembly: bool) -> Self {
DataType {
level: Level::Connection,
needs_parse: false,
track_sessions: false,
needs_update: !reassembly,
needs_update_reassembled: reassembly,
stream_protos: vec![],
as_str,
}
Expand Down Expand Up @@ -208,15 +214,6 @@ impl DataType {
}
}

// Helper
fn track_packets(&self, actions: &mut MatchingActions) {
if self.track_packets {
actions.if_matched.data |= ActionData::PacketTrack;
actions.if_matched.terminal_actions |= ActionData::PacketTrack;
actions.if_matching.data |= ActionData::PacketTrack;
}
}

// Helper for proto_filter and session_filter
fn track_sessions(&self, actions: &mut MatchingActions, sub_level: &Level) {
// SessionTrack should only be terminal if matched at packet layer
Expand Down Expand Up @@ -251,7 +248,6 @@ impl DataType {

// Connection- and session-level subscriptions depend on the actions required
self.needs_update(&mut actions);
self.track_packets(&mut actions);
self.conn_deliver(sub_level, &mut actions);

if self.needs_parse {
Expand Down Expand Up @@ -292,7 +288,6 @@ impl DataType {

// Connection- and session-level subscriptions depend on the actions required
self.needs_update(&mut actions);
self.track_packets(&mut actions);
self.track_sessions(&mut actions, sub_level);
self.conn_deliver(sub_level, &mut actions);

Expand All @@ -316,7 +311,6 @@ impl DataType {
}

self.needs_update(&mut actions);
self.track_packets(&mut actions);
self.track_sessions(&mut actions, sub_level);
self.conn_deliver(sub_level, &mut actions);

Expand Down
2 changes: 1 addition & 1 deletion core/src/filter/ptree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ impl PTree {
// is equivalent performance-wise to implementing similar functionality in the
// framework.
panic!("Cannot access per-packet fields (e.g., TCP flags, length) after packet filter.\n\
Subscribe to `ZcFrame` or PacketList instead.");
Subscribe to `ZcFrame` or list of mbufs instead.");
}

// Predicate is already present
Expand Down
13 changes: 13 additions & 0 deletions core/src/memory/mbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ impl Mbuf {
})
}

pub fn new_ref(mbuf: &Mbuf) -> Mbuf {
unsafe {
dpdk::rte_mbuf_refcnt_update(mbuf.raw.as_ptr(), 1);
}
Mbuf::new_unchecked(mbuf.raw.as_ptr())
}

/// Creates a new Mbuf from a byte slice.
pub(crate) fn from_bytes(data: &[u8], mp: *mut dpdk::rte_mempool) -> Result<Mbuf> {
let mut mbuf = unsafe { Mbuf::new(dpdk::rte_pktmbuf_alloc(mp))? };
Expand Down Expand Up @@ -181,6 +188,12 @@ impl<'a> Packet<'a> for Mbuf {
impl Drop for Mbuf {
fn drop(&mut self) {
// log::debug!("Dropping a Mbuf, freeing mbuf@{:p}", self.raw().buf_addr);

// Reference counting allows Mbufs to be shared across data structures
// (e.g., store in pre-reassembly and post-reassembly order) and cores.
// Using DPDK built-ins to manage reference counting is more efficient
// than Rust standard library (Rc or Arc). Note `rte_pktmbuf_free` updates
// refcount internally and only releases the mbuf if refcount becomes 0.
unsafe { dpdk::rte_pktmbuf_free(self.raw()) };
}
}
Expand Down
16 changes: 16 additions & 0 deletions datatypes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub mod packet;
pub use packet::{Payload, ZcFrame};
pub mod static_type;
pub use static_type::*;
pub mod packet_list;
pub use packet_list::*;
pub use typedefs::*;

use retina_core::conntrack::pdu::L4Pdu;
Expand Down Expand Up @@ -92,3 +94,17 @@ pub trait FromSubscription {
/// the constant value (e.g., matched filter string).
fn from_subscription(spec: &SubscriptionSpec) -> proc_macro2::TokenStream;
}

/// Trait for a datatype that is built from a list of raw packets.
pub trait PacketList {
/// Initialize internal data; called once per connection.
/// Note `first_pkt` will also be delivered to `update`.
fn new(first_pkt: &L4Pdu) -> Self;
/// New packet in connection received (or reassembled, if reassembled=true)
/// Note this may be invoked both pre- and post-reassembly; types
/// should check `reassembled` to avoid double-counting.
fn update(&mut self, pdu: &L4Pdu, reassembled: bool);
/// Clear internal data; called if connection no longer matches filter
/// that requires the Tracked type.
fn clear(&mut self);
}
Loading

0 comments on commit 5598165

Please sign in to comment.