Skip to content

Commit

Permalink
tests: add kernel test
Browse files Browse the repository at this point in the history
  • Loading branch information
hack3ric committed Jan 1, 2025
1 parent c93b31a commit 6a7b7ac
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 32 deletions.
72 changes: 72 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ test-case = "3.3.1"
version-compare = "0.2.0"
tokio = { version = "1.38.0", features = ["time"] }
macro_rules_attribute = "0.2.0"
rand = "0.8.5"

[profile.release]
opt-level = "z"
Expand Down
34 changes: 3 additions & 31 deletions src/integration_tests/flowspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::args::Cli;
use crate::bgp::flow::Component::*;
use crate::bgp::flow::{Flowspec, Op};
use crate::bgp::route::{AsSegment, ExtCommunity, GlobalAdmin, Origin, RouteInfo, TrafficFilterAction};
use crate::integration_tests::BIRD_CONFIG_1;
use anyhow::Context;
use clap::Parser;
use macro_rules_attribute::apply;
Expand Down Expand Up @@ -131,34 +132,6 @@ async fn run_flowspec_test(flows: impl IntoIterator<Item = (&str, Flowspec, Rout
}

async fn run_flowspec_test_inner(mut flows: BTreeMap<Flowspec, (&str, RouteInfo<'_>)>) -> anyhow::Result<()> {
const BIRD_FILE: &str = "\
router id 10.234.56.78;
flow4 table myflow4;
flow6 table myflow6;
protocol static f4 {
flow4 { table myflow4; };
@@FLOW4@@;
}
protocol static f6 {
flow6 { table myflow6; };
@@FLOW6@@;
}
protocol bgp flow_test {
debug all;
connect delay time 1;
local ::1 port @@BIRD_PORT@@ as 65000;
neighbor ::1 port @@FLOW_PORT@@ as 65000;
multihop;
flow4 { table myflow4; import none; export all; };
flow6 { table myflow6; import none; export all; };
}";

ensure_bird_2();
ensure_loopback_up().await?;

Expand All @@ -180,20 +153,19 @@ protocol bgp flow_test {
"--local-as=65000",
"--remote-as=65000",
])?;
let bird = BIRD_FILE
let bird = BIRD_CONFIG_1
.replace("@@BIRD_PORT@@", &pick_port().await?.to_string())
.replace("@@FLOW_PORT@@", &flow_port)
.replace("@@FLOW4@@", &flow4)
.replace("@@FLOW6@@", &flow6);

let (mut cli, mut bird, mut events, close, _g) = run_cli_with_bird(cli, &bird).await?;

let mut end_of_rib_count = 0;
let mut visited = BTreeSet::new();
let _state = 'outer: loop {
select! {
Some(event) = events.recv(), if !events.is_closed() => match event {
TestEvent::EndOfRib(_afi, _safi) => {
TestEvent::EndOfRib(..) => {
end_of_rib_count += 1;
if end_of_rib_count >= 2 {
let _ = close.send(());
Expand Down
1 change: 0 additions & 1 deletion src/integration_tests/helpers/kernel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use nix::unistd::Uid;
use tokio::net::TcpListener;

#[expect(unused)]
pub fn ensure_root() {
assert!(
Uid::effective().is_root(),
Expand Down
91 changes: 91 additions & 0 deletions src/integration_tests/kernel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use super::helpers::cli::CliChild;
use crate::args::Cli;
use crate::integration_tests::helpers::bird::ensure_bird_2;
use crate::integration_tests::helpers::cli::run_cli_with_bird;
use crate::integration_tests::helpers::kernel::{ensure_loopback_up, ensure_root, pick_port};
use crate::integration_tests::{TestEvent, BIRD_CONFIG_1};
use async_tempfile::{TempDir, TempFile};
use clap::Parser;
use macro_rules_attribute::apply;
use rand::distributions::Alphanumeric;
use rand::Rng;
use std::time::Duration;
use tokio::process::Child;
use tokio::select;
use tokio::sync::oneshot;
use tokio::time::sleep;

#[apply(test_local!)]
async fn test_nftables() -> anyhow::Result<()> {
let (name, _g) = run_kernel_test([
"flow4 { dst 10.0.0.0/9; length > 1024; } { bgp_ext_community.add((unknown 0x8006, 0, 0x4c97a25c)); }",
])
.await?;

let chain =
nftables::helper::get_current_ruleset_async(None, Some(&["-ns", "list", "chain", "inet", &name, &name])).await?;
println!("{chain:?}");
Ok(())
}

type Guard = (CliChild, Child, oneshot::Sender<()>, (TempFile, TempDir));

async fn run_kernel_test(flows: impl IntoIterator<Item = &str>) -> anyhow::Result<(String, Guard)> {
ensure_bird_2();
ensure_root();
ensure_loopback_up().await?;

let (flow4, flow6) = flows.into_iter().fold((String::new(), String::new()), |(v4, v6), str| {
if str.starts_with("flow4") {
(v4 + "route " + str + ";", v6)
} else {
(v4, v6 + "route " + str + ";")
}
});

let table_name: String = "flow_test_"
.chars()
.chain(rand::thread_rng().sample_iter(&Alphanumeric).take(8).map(char::from))
.collect();
let flow_port = pick_port().await?.to_string();
let cli = Cli::try_parse_from([
"flow",
"run",
"-v",
&format!("--bind=[::1]:{flow_port}"),
"--local-as=65000",
"--remote-as=65000",
"--table",
&table_name,
"--chain",
&table_name,
])?;
let bird = BIRD_CONFIG_1
.replace("@@BIRD_PORT@@", &pick_port().await?.to_string())
.replace("@@FLOW_PORT@@", &flow_port)
.replace("@@FLOW4@@", &flow4)
.replace("@@FLOW6@@", &flow6);

let (mut cli, mut bird, mut events, close, g) = run_cli_with_bird(cli, &bird).await?;
let mut end_of_rib_count = 0;
loop {
select! {
Some(event) = events.recv(), if !events.is_closed() => match event {
TestEvent::EndOfRib(..) => {
end_of_rib_count += 1;
if end_of_rib_count >= 2 {
break;
}
}
TestEvent::Update(_) => {},
TestEvent::Exit(_) => panic!("unexpected CLI exit event"),
},
_ = sleep(Duration::from_secs(10)) => panic!("timed out"),
code = &mut cli => panic!("CLI exited early with code {}", code??),
status = bird.wait() => panic!("BIRD exited early with {}", status?),
}
}

let guard = (cli, bird, close, g);
Ok((table_name, guard))
}
29 changes: 29 additions & 0 deletions src/integration_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,32 @@ pub(crate) use test_local;

// Test files
mod flowspec;
mod kernel;

const BIRD_CONFIG_1: &str = "\
router id 10.234.56.78;
flow4 table myflow4;
flow6 table myflow6;
protocol static f4 {
flow4 { table myflow4; };
@@FLOW4@@
}
protocol static f6 {
flow6 { table myflow6; };
@@FLOW6@@
}
protocol bgp flow_test {
debug all;
connect delay time 1;
local ::1 port @@BIRD_PORT@@ as 65000;
neighbor ::1 port @@FLOW_PORT@@ as 65000;
multihop;
flow4 { table myflow4; import none; export all; };
flow6 { table myflow6; import none; export all; };
}";

0 comments on commit 6a7b7ac

Please sign in to comment.