diff --git a/src/bgp/mod.rs b/src/bgp/mod.rs index f36010b..91f2ff0 100644 --- a/src/bgp/mod.rs +++ b/src/bgp/mod.rs @@ -4,7 +4,7 @@ pub mod nlri; pub mod route; use crate::args::RunArgs; -use crate::kernel::{self, Kernel}; +use crate::kernel::{self, KernelAdapter}; use crate::net::{Afi, IpPrefixError, IpPrefixErrorKind}; use either::Either; use flow::FlowError; @@ -62,9 +62,9 @@ pub struct Session { impl Session { pub async fn new(c: RunArgs) -> Result { let kernel = if c.dry_run { - Kernel::Noop + KernelAdapter::Noop } else { - Kernel::linux(c.kernel.clone()).await? + KernelAdapter::linux(c.kernel.clone()).await? }; Ok(Self { config: c, state: Active, routes: Routes::new(kernel) }) } diff --git a/src/bgp/route.rs b/src/bgp/route.rs index 7381275..e89b912 100644 --- a/src/bgp/route.rs +++ b/src/bgp/route.rs @@ -22,11 +22,11 @@ use strum::{EnumDiscriminants, FromRepr}; pub struct Routes { unicast: BTreeMap>)>, flow: BTreeMap>)>, - kernel: Kernel, + kernel: KernelAdapter, } impl Routes { - pub fn new(kernel: Kernel) -> Self { + pub fn new(kernel: KernelAdapter) -> Self { Self { unicast: BTreeMap::new(), flow: BTreeMap::new(), kernel } } diff --git a/src/kernel/linux/mod.rs b/src/kernel/linux/mod.rs index 0e886c7..886383c 100644 --- a/src/kernel/linux/mod.rs +++ b/src/kernel/linux/mod.rs @@ -1,7 +1,7 @@ mod nft; use super::rtnl::{RtNetlink, RtNetlinkArgs}; -use super::{KernelAdapter, Result}; +use super::{Kernel, Result}; use crate::bgp::flow::Flowspec; use crate::bgp::route::RouteInfo; use clap::Args; @@ -35,7 +35,7 @@ impl Linux { } } -impl KernelAdapter for Linux { +impl Kernel for Linux { type Handle = u64; async fn apply(&mut self, spec: &Flowspec, info: &RouteInfo<'_>) -> Result { diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index 9d1c7ee..cc3c1a7 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -1,7 +1,7 @@ //! Bridges flowspecs to OS kernel. //! -//! Currently only Linux is supported, which uses nftables. Future support may -//! include *BSD using `pf` as backend. +//! Currently only Linux is supported. Future support may include *BSD using +//! `pf` as backend. #[cfg(target_os = "linux")] mod linux; @@ -19,30 +19,42 @@ use std::future::Future; use strum::Display; use thiserror::Error; -pub trait KernelAdapter { +/// Interface between BGP flowspec and the OS. +pub trait Kernel { + /// Type representing a flowspec's counterpart in kernel. type Handle; + + /// Apply a flowspec to kernel. fn apply(&mut self, spec: &Flowspec, info: &RouteInfo<'_>) -> impl Future>; + + /// Remove a flowspec from kernel using previously returned handle. fn remove(&mut self, handle: Self::Handle) -> impl Future>; + + /// Process notifications from kernel, timers, etc. fn process(&mut self) -> impl Future> { pending() } } +/// Adapter of different `Kernel` implementations. #[derive(Debug, Serialize, Deserialize)] -pub enum Kernel { +pub enum KernelAdapter { + /// Do nothing. Noop, + + /// Linux implementation, using nftables and rtnetlink. #[cfg(target_os = "linux")] Linux(Linux), } -impl Kernel { +impl KernelAdapter { #[cfg(target_os = "linux")] pub async fn linux(args: KernelArgs) -> Result { Ok(Self::Linux(Linux::new(args).await?)) } } -impl KernelAdapter for Kernel { +impl Kernel for KernelAdapter { type Handle = KernelHandle; async fn apply(&mut self, spec: &Flowspec, info: &RouteInfo<'_>) -> Result { @@ -75,7 +87,7 @@ pub enum KernelHandle { #[cfg(target_os = "linux")] #[strum(to_string = "{0}")] - Linux(::Handle), + Linux(::Handle), } #[derive(Debug, Error)] diff --git a/src/kernel/rtnl.rs b/src/kernel/rtnl.rs index bbbc23e..28523a9 100644 --- a/src/kernel/rtnl.rs +++ b/src/kernel/rtnl.rs @@ -65,6 +65,7 @@ impl RtNetlink { .filter(|(_, v)| v.iter().all(|p| !p.overlaps(prefix))) .next() { + // there's a table whose content doesn't overlap with our prefix, we reuse it prefixes.insert(prefix); *table_id } else { @@ -84,7 +85,6 @@ impl RtNetlink { .priority(self.args.rt_rule_priority) .execute() .await?; - self.handle.rule().get(rtnetlink::IpVersion::V4); table_id };