diff --git a/lib/opte/src/ddi/kstat.rs b/lib/opte/src/ddi/kstat.rs index f6496ff9..63b2f413 100644 --- a/lib/opte/src/ddi/kstat.rs +++ b/lib/opte/src/ddi/kstat.rs @@ -61,7 +61,7 @@ cfg_if! { /// ``` /// /// To register a provider see [`KStatNamed`]. -pub trait KStatProvider { +pub trait KStatProvider: Send + Sync { const NUM_FIELDS: u32; type Snap; @@ -306,3 +306,19 @@ impl From for Error { Self::NulChar } } + +// SAFETY: KStatNamed is safe for Send + Sync because: +// +// 1. The underlying T must itself be Send + Sync because it is fully visible to any +// user of the struct. We meet this through the new type bound on KStatProvider. +// +// 2. ksp is itself safe to move between threads, since KSTAT(9S) imposes no MT +// constraints on callers. +// +// 3. ksp is never exposed via a &ref (nor is it used by any +// methods taking &self), and is only used during drop. +// +#[cfg(all(not(feature = "std"), not(test)))] +unsafe impl Send for KStatNamed {} +#[cfg(all(not(feature = "std"), not(test)))] +unsafe impl Sync for KStatNamed {} diff --git a/lib/opte/src/engine/flow_table.rs b/lib/opte/src/engine/flow_table.rs index fa70cc0e..cbbb7d42 100644 --- a/lib/opte/src/engine/flow_table.rs +++ b/lib/opte/src/engine/flow_table.rs @@ -64,7 +64,7 @@ impl Ttl { } /// A policy for expiring flow table entries over time. -pub trait ExpiryPolicy: fmt::Debug { +pub trait ExpiryPolicy: fmt::Debug + Send + Sync { /// Returns whether the given flow should be removed, given current flow /// state, the time a packet was last received, and the current time. fn is_expired(&self, entry: &FlowEntry, now: Moment) -> bool; diff --git a/lib/opte/src/engine/rule.rs b/lib/opte/src/engine/rule.rs index 141b31e4..4247adb8 100644 --- a/lib/opte/src/engine/rule.rs +++ b/lib/opte/src/engine/rule.rs @@ -173,7 +173,7 @@ where /// An Action Descriptor holds the information needed to create the /// [`HdrTransform`] which implements the desired action. An /// ActionDesc is created by a [`StatefulAction`] implementation. -pub trait ActionDesc { +pub trait ActionDesc: Send + Sync { /// Generate the [`HdrTransform`] which implements this descriptor. fn gen_ht(&self, dir: Direction) -> HdrTransform; @@ -742,7 +742,7 @@ pub enum GenDescError { pub type GenDescResult = ActionResult, GenDescError>; -pub trait StatefulAction: Display { +pub trait StatefulAction: Display + Send + Sync { /// Generate a an [`ActionDesc`] based on the [`InnerFlowId`] and /// [`ActionMeta`]. This action may also add, remove, or modify /// metadata to communicate data to downstream actions. @@ -772,7 +772,7 @@ pub enum GenHtError { pub type GenHtResult = ActionResult; -pub trait StaticAction: Display { +pub trait StaticAction: Display + Send + Sync { fn gen_ht( &self, dir: Direction, @@ -795,7 +795,7 @@ pub type ModMetaResult = ActionResult<(), String>; /// metadata in some way. That is, it has no transformation to make on /// the packet, only add/modify/remove metadata for use by later /// layers. -pub trait MetaAction: Display { +pub trait MetaAction: Display + Send + Sync { /// Return the predicates implicit to this action. /// /// Return both the header [`Predicate`] list and @@ -843,7 +843,7 @@ impl From for GenBtError { /// /// For example, you could use this to hairpin an ARP Reply in response /// to a guest's ARP request. -pub trait HairpinAction: Display { +pub trait HairpinAction: Display + Send + Sync { /// Generate a [`Packet`] to hairpin back to the source. The /// `meta` argument holds the packet metadata, including any /// modifications made by previous layers up to this point. diff --git a/lib/opte/src/engine/snat.rs b/lib/opte/src/engine/snat.rs index e8e4f121..d3bbff22 100644 --- a/lib/opte/src/engine/snat.rs +++ b/lib/opte/src/engine/snat.rs @@ -218,7 +218,7 @@ impl From for GenDescError { } } -impl SNat { +impl SNat { pub fn new(addr: T) -> Self { SNat { priv_ip: addr, @@ -299,7 +299,7 @@ impl Display for SNat { } } -impl StatefulAction for SNat +impl StatefulAction for SNat where SNat: Display, { @@ -367,7 +367,7 @@ pub struct SNatDesc { pub const SNAT_NAME: &str = "SNAT"; -impl ActionDesc for SNatDesc { +impl ActionDesc for SNatDesc { fn gen_ht(&self, dir: Direction) -> HdrTransform { match dir { // Outbound traffic needs its source IP and source port @@ -425,7 +425,7 @@ pub struct SNatIcmpEchoDesc { pub const SNAT_ICMP_ECHO_NAME: &str = "SNAT_ICMP_ECHO"; -impl ActionDesc for SNatIcmpEchoDesc { +impl ActionDesc for SNatIcmpEchoDesc { // SNAT needs to generate an additional transform for ICMP traffic in // order to treat the Echo Identifier as a psuedo ULP port. fn gen_ht(&self, dir: Direction) -> HdrTransform { diff --git a/lib/opte/src/lib.rs b/lib/opte/src/lib.rs index 6de57220..6c62d544 100644 --- a/lib/opte/src/lib.rs +++ b/lib/opte/src/lib.rs @@ -200,7 +200,7 @@ mod opte_provider { /// /// Logging levels are provided by [`LogLevel`]. These levels will map /// to the underlying provider with varying degrees of success. -pub trait LogProvider { +pub trait LogProvider: Send + Sync { /// Log a message at the specified level. fn log(&self, level: LogLevel, msg: &str); }