Skip to content

Commit

Permalink
Merge pull request #421 from retis-org/at/section-id-untangle
Browse files Browse the repository at this point in the history
Untangle the section id, factories and modules
  • Loading branch information
amorenoz authored Oct 7, 2024
2 parents 6141f13 + 717bfee commit 77b303a
Show file tree
Hide file tree
Showing 29 changed files with 367 additions and 350 deletions.
73 changes: 44 additions & 29 deletions retis-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use proc_macro::{self, TokenStream};
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Item, ItemStruct};
use syn::{parse_macro_input, Item, ItemStruct};

#[proc_macro_attribute]
pub fn raw_event_section(
Expand All @@ -24,39 +23,22 @@ pub fn event_section(
let input: ItemStruct = parse_macro_input!(item);
let ident = &input.ident;

let name: syn::LitStr = syn::parse(args).expect("Invalid event name");
let id: syn::Expr = syn::parse(args).expect("Invalid event id");

let output = quote! {
#[derive(Default, crate::EventSection)]
#[derive(Default)]
#[crate::event_type]
#input

impl #ident {
pub(crate) const SECTION_NAME: &'static str = #name;
pub(crate) const SECTION_ID: u8 = #id as u8;
}
};
output.into()
}

#[proc_macro_attribute]
pub fn event_type(
_: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input: Item = parse_macro_input!(item);
let output = quote! {
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
#input
};
output.into()
}

#[proc_macro_derive(EventSection)]
pub fn derive_event_section(input: TokenStream) -> TokenStream {
let DeriveInput { ident, .. } = parse_macro_input!(input);
let output = quote! {
impl EventSectionInternal for #ident {
fn id(&self) -> u8 {
Self::SECTION_ID
}

fn as_any(&self) -> &dyn std::any::Any
where Self: Sized,
{
Expand All @@ -79,13 +61,46 @@ pub fn derive_event_section(input: TokenStream) -> TokenStream {
output.into()
}

#[proc_macro_derive(EventSectionFactory)]
pub fn derive_event_section_factory(input: TokenStream) -> TokenStream {
let input: DeriveInput = parse_macro_input!(input);
#[proc_macro_attribute]
pub fn event_type(
_: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let output = format!(
r#"
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
{item}
"#
);
output
.parse()
.expect("Invalid tokens from event_section macro")
}

#[proc_macro_attribute]
pub fn event_section_factory(
args: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input: ItemStruct = parse_macro_input!(item);
let ident = &input.ident;

let id: syn::Expr = syn::parse(args).expect("Invalid factory id");

let output = quote! {
#input

impl #ident {
pub(crate) const FACTORY_ID: u8 = #id as u8;

}

impl EventSectionFactory for #ident {
fn id(&self) -> u8 {
Self::FACTORY_ID
}

fn as_any_mut(&mut self) -> &mut dyn std::any::Any
where Self: Sized,
{
Expand Down
4 changes: 2 additions & 2 deletions retis-events/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::*;

/// Startup event section. Contains global information about a collection as a
/// whole, with data gathered at collection startup time.
#[event_section("startup")]
#[event_section(SectionId::Startup)]
pub struct StartupEvent {
/// Retis version used while collecting events.
pub retis_version: String,
Expand All @@ -33,7 +33,7 @@ pub struct TaskEvent {
}

/// Common event section.
#[event_section("common")]
#[event_section(SectionId::Common)]
pub struct CommonEvent {
/// Timestamp of when the event was generated.
pub timestamp: u64,
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/ct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub enum CtState {
Untracked,
}
/// Conntrack event
#[event_section("ct")]
#[event_section(SectionId::Ct)]
pub struct CtEvent {
/// Packet's conntrack state
pub state: CtState,
Expand Down
136 changes: 43 additions & 93 deletions retis-events/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#![allow(dead_code)] // FIXME
#![allow(clippy::wrong_self_convention)]

use std::{any::Any, collections::HashMap, fmt, str::FromStr};
use std::{any::Any, collections::HashMap, fmt};

use anyhow::{anyhow, bail, Result};
use log::debug;
Expand All @@ -60,18 +60,15 @@ impl Event {
.map_err(|e| anyhow!("Failed to parse json event at line {line}: {e}"))?;

for (owner, value) in event_js.drain() {
let owner_mod = SectionId::from_str(&owner)?;
let parser = event_sections()?
.get(&owner)
.ok_or_else(|| anyhow!("json contains an unsupported event {}", owner))?;

debug!("Unmarshaling event section {owner}: {value}");
event.insert_section(
owner_mod,
parser(value).map_err(|e| {
anyhow!("Failed to create EventSection for owner {owner} from json: {e}")
})?,
)?;
let section = parser(value).map_err(|e| {
anyhow!("Failed to create EventSection for owner {owner} from json: {e}")
})?;
event.insert_section(SectionId::from_u8(section.id())?, section)?;
}
Ok(event)
}
Expand Down Expand Up @@ -166,7 +163,7 @@ impl EventFmt for Event {
f.conf.inc_level(2);

// Finally show all sections.
(SectionId::Skb.to_u8()..SectionId::_MAX.to_u8())
(SectionId::Skb as u8..SectionId::_MAX as u8)
.collect::<Vec<u8>>()
.iter()
.filter_map(|id| self.0.get(&SectionId::from_u8(*id).unwrap()))
Expand Down Expand Up @@ -198,29 +195,6 @@ pub enum SectionId {
_MAX = 12,
}

impl FromStr for SectionId {
type Err = anyhow::Error;

/// Constructs an SectionId from a section unique str identifier.
fn from_str(val: &str) -> Result<Self> {
use SectionId::*;
Ok(match val {
CommonEvent::SECTION_NAME => Common,
KernelEvent::SECTION_NAME => Kernel,
UserEvent::SECTION_NAME => Userspace,
TrackingInfo::SECTION_NAME => Tracking,
SkbTrackingEvent::SECTION_NAME => SkbTracking,
SkbDropEvent::SECTION_NAME => SkbDrop,
SkbEvent::SECTION_NAME => Skb,
OvsEvent::SECTION_NAME => Ovs,
NftEvent::SECTION_NAME => Nft,
CtEvent::SECTION_NAME => Ct,
StartupEvent::SECTION_NAME => Startup,
x => bail!("Can't construct a SectionId from {}", x),
})
}
}

impl SectionId {
/// Constructs an SectionId from a section unique identifier
pub fn from_u8(val: u8) -> Result<SectionId> {
Expand All @@ -241,41 +215,21 @@ impl SectionId {
})
}

/// Converts an SectionId to a section unique identifier.
#[allow(dead_code)]
pub fn to_u8(self) -> u8 {
use SectionId::*;
match self {
Common => 1,
Kernel => 2,
Userspace => 3,
Tracking => 4,
SkbTracking => 5,
SkbDrop => 6,
Skb => 7,
Ovs => 8,
Nft => 9,
Ct => 10,
Startup => 11,
_MAX => 12,
}
}

/// Converts an SectionId to a section unique str identifier.
pub fn to_str(self) -> &'static str {
use SectionId::*;
match self {
Common => CommonEvent::SECTION_NAME,
Kernel => KernelEvent::SECTION_NAME,
Userspace => UserEvent::SECTION_NAME,
Tracking => TrackingInfo::SECTION_NAME,
SkbTracking => SkbTrackingEvent::SECTION_NAME,
SkbDrop => SkbDropEvent::SECTION_NAME,
Skb => SkbEvent::SECTION_NAME,
Ovs => OvsEvent::SECTION_NAME,
Nft => NftEvent::SECTION_NAME,
Ct => CtEvent::SECTION_NAME,
Startup => StartupEvent::SECTION_NAME,
Common => "common",
Kernel => "kernel",
Userspace => "userspace",
Tracking => "tracking",
SkbTracking => "skb-tracking",
SkbDrop => "skb-drop",
Skb => "skb",
Ovs => "ovs",
Nft => "nft",
Ct => "ct",
Startup => "startup",
_MAX => "_max",
}
}
Expand All @@ -291,39 +245,30 @@ impl fmt::Display for SectionId {
type EventSectionMap = HashMap<String, fn(serde_json::Value) -> Result<Box<dyn EventSection>>>;
static EVENT_SECTIONS: OnceCell<EventSectionMap> = OnceCell::new();

macro_rules! insert_section {
($events: expr, $ty: ty) => {
$events.insert(
SectionId::from_u8(<$ty>::SECTION_ID)?.to_str().to_string(),
|v| Ok(Box::new(serde_json::from_value::<$ty>(v)?)),
);
};
}

fn event_sections() -> Result<&'static EventSectionMap> {
EVENT_SECTIONS.get_or_try_init(|| {
let mut events = EventSectionMap::new();
events.insert(CommonEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<CommonEvent>(v)?))
});
events.insert(KernelEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<KernelEvent>(v)?))
});
events.insert(UserEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<UserEvent>(v)?))
});
events.insert(SkbTrackingEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<SkbTrackingEvent>(v)?))
});
events.insert(SkbDropEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<SkbDropEvent>(v)?))
});
events.insert(SkbEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<SkbEvent>(v)?))
});
events.insert(OvsEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<OvsEvent>(v)?))
});
events.insert(NftEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<NftEvent>(v)?))
});
events.insert(CtEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<CtEvent>(v)?))
});
events.insert(StartupEvent::SECTION_NAME.to_string(), |v| {
Ok(Box::new(serde_json::from_value::<StartupEvent>(v)?))
});

insert_section!(events, CommonEvent);
insert_section!(events, KernelEvent);
insert_section!(events, UserEvent);
insert_section!(events, SkbTrackingEvent);
insert_section!(events, SkbDropEvent);
insert_section!(events, SkbEvent);
insert_section!(events, OvsEvent);
insert_section!(events, NftEvent);
insert_section!(events, CtEvent);
insert_section!(events, StartupEvent);

Ok(events)
})
}
Expand Down Expand Up @@ -358,6 +303,7 @@ impl<T> EventSection for T where T: EventSectionInternal + for<'a> EventDisplay<
///
/// There should not be a need to have per-object implementations for this.
pub trait EventSectionInternal {
fn id(&self) -> u8;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn to_json(&self) -> serde_json::Value;
Expand All @@ -366,6 +312,10 @@ pub trait EventSectionInternal {
// We need this as the value given as the input when deserializing something
// into an event could be mapped to (), e.g. serde_json::Value::Null.
impl EventSectionInternal for () {
fn id(&self) -> u8 {
SectionId::_MAX as u8
}

fn as_any(&self) -> &dyn Any {
self
}
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fmt;
use super::*;
use crate::{event_section, event_type, Formatter};

#[event_section("kernel")]
#[event_section(SectionId::Kernel)]
pub struct KernelEvent {
/// Kernel symbol name associated with the event (i.e. which probe generated
/// the event).
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::*;
use crate::{event_section, Formatter};

/// Nft event section
#[event_section("nft")]
#[event_section(SectionId::Nft)]
pub struct NftEvent {
pub table_name: String,
pub chain_name: String,
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/ovs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{event_section, event_type, Formatter};

///The OVS Event
#[derive(PartialEq)]
#[event_section("ovs")]
#[event_section(SectionId::Ovs)]
pub struct OvsEvent {
/// Event data
#[serde(flatten)]
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/skb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{
use crate::{event_section, event_type, Formatter};

/// Skb event section.
#[event_section("skb")]
#[event_section(SectionId::Skb)]
pub struct SkbEvent {
/// Ethernet fields, if any.
pub eth: Option<SkbEthEvent>,
Expand Down
2 changes: 1 addition & 1 deletion retis-events/src/skb_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::*;
use crate::{event_section, Formatter};

/// Skb drop event section.
#[event_section("skb-drop")]
#[event_section(SectionId::SkbDrop)]
pub struct SkbDropEvent {
/// Sub-system who generated the below drop reason. None for core reasons.
pub subsys: Option<String>,
Expand Down
4 changes: 2 additions & 2 deletions retis-events/src/skb_tracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{event_section, Formatter};
/// Tl;dr; the tracking unique id is `(timestamp, orig_head)` and `skb` can be
/// used to distinguished between clones.
#[derive(Copy, PartialEq)]
#[event_section("skb-tracking")]
#[event_section(SectionId::SkbTracking)]
#[repr(C)]
pub struct SkbTrackingEvent {
/// Head of buffer (`skb->head`) when the packet was first seen by the
Expand Down Expand Up @@ -54,7 +54,7 @@ impl EventFmt for SkbTrackingEvent {

/// Tracking event section. Generated at postprocessing with combined skb and ovs
/// tracking information.
#[event_section("tracking")]
#[event_section(SectionId::Tracking)]
pub struct TrackingInfo {
/// Tracking information of the original packet.
pub skb: SkbTrackingEvent,
Expand Down
Loading

0 comments on commit 77b303a

Please sign in to comment.