blob: 864d48375e80f670985d046db267b5e586fa360f [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use core::fmt::Debug;
use net_types::ip::{Ipv4, Ipv6};
use netstack3_base::{InstantBindingsTypes, InstantContext};
use packet_formats::ip::IpExt;
use crate::state::State;
/// Trait defining required types for filtering provided by bindings.
///
/// Allows rules that match on device class to be installed, storing the
/// [`FilterBindingsTypes::DeviceClass`] type at rest, while allowing Netstack3
/// Core to have Bindings provide the type since it is platform-specific.
pub trait FilterBindingsTypes: InstantBindingsTypes {
/// The device class type for devices installed in the netstack.
type DeviceClass: Clone + Debug;
}
/// Trait aggregating functionality required from bindings.
pub trait FilterBindingsContext: InstantContext + FilterBindingsTypes {}
impl<BC: InstantContext + FilterBindingsTypes> FilterBindingsContext for BC {}
/// The IP version-specific execution context for packet filtering.
///
/// This trait exists to abstract over access to the filtering state. It is
/// useful to implement filtering logic in terms of this trait, as opposed to,
/// for example, [`crate::logic::FilterHandler`] methods taking the state
/// directly as an argument, because it allows Netstack3 Core to use lock
/// ordering types to enforce that filtering state is only acquired at or before
/// a given lock level, while keeping test code free of locking concerns.
pub trait FilterIpContext<I: IpExt, BT: FilterBindingsTypes> {
/// Calls the function with a reference to filtering state.
fn with_filter_state<O, F: FnOnce(&State<I, BT>) -> O>(&mut self, cb: F) -> O;
}
/// A context for mutably accessing all filtering state at once, to allow IPv4
/// and IPv6 filtering state to be modified atomically.
pub trait FilterContext<BT: FilterBindingsTypes> {
/// Calls the function with a mutable reference to all filtering state.
fn with_all_filter_state_mut<O, F: FnOnce(&mut State<Ipv4, BT>, &mut State<Ipv6, BT>) -> O>(
&mut self,
cb: F,
) -> O;
}
#[cfg(test)]
pub(crate) mod testutil {
use core::time::Duration;
use netstack3_base::testutil::FakeInstant;
use super::*;
use crate::{
conntrack,
state::{validation::ValidRoutines, IpRoutines, Routines},
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum FakeDeviceClass {
Ethernet,
Wlan,
}
pub enum FakeBindingsTypes {}
impl InstantBindingsTypes for FakeBindingsTypes {
type Instant = FakeInstant;
}
impl FilterBindingsTypes for FakeBindingsTypes {
type DeviceClass = FakeDeviceClass;
}
pub struct FakeCtx<I: IpExt, BT: FilterBindingsTypes>(State<I, BT>);
impl<I: IpExt, BT: FilterBindingsTypes> FakeCtx<I, BT> {
#[allow(dead_code)]
pub fn with_ip_routines(routines: IpRoutines<I, BT::DeviceClass, ()>) -> Self {
let (installed_routines, uninstalled_routines) =
ValidRoutines::new(Routines { ip: routines, ..Default::default() })
.expect("invalid state");
Self(State {
installed_routines,
uninstalled_routines,
conntrack: conntrack::Table::new(),
})
}
}
impl<I: IpExt> FilterIpContext<I, FakeBindingsTypes> for FakeCtx<I, FakeBindingsTypes> {
fn with_filter_state<O, F: FnOnce(&State<I, FakeBindingsTypes>) -> O>(
&mut self,
cb: F,
) -> O {
let Self(state) = self;
cb(&*state)
}
}
#[derive(Debug)]
pub struct FakeBindingsCtx {
time_elapsed: Duration,
}
#[allow(dead_code)]
impl FakeBindingsCtx {
pub(crate) fn new() -> Self {
Self { time_elapsed: Duration::from_secs(0) }
}
pub(crate) fn set_time_elapsed(&mut self, time_elapsed: Duration) {
self.time_elapsed = time_elapsed;
}
}
impl InstantBindingsTypes for FakeBindingsCtx {
type Instant = FakeInstant;
}
impl FilterBindingsTypes for FakeBindingsCtx {
type DeviceClass = FakeDeviceClass;
}
impl InstantContext for FakeBindingsCtx {
fn now(&self) -> Self::Instant {
Self::Instant { offset: self.time_elapsed }
}
}
}