Skip to content

Commit 9b0200a

Browse files
Merge branch 'feature/ebpf-core' into identity_enhancements
2 parents 7416651 + 228042c commit 9b0200a

File tree

14 files changed

+111232
-2
lines changed

14 files changed

+111232
-2
lines changed

core/Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ members = [
1414
"src/components/maps",
1515
"src/components/conntracker",
1616
"xtask",
17-
"src/components/identity",
17+
"src/components/identity", "src/components/metrics_tracer", "src/components/metrics",
1818
]
1919

2020
[dependencies]

core/Readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ If you're interested or have any questions, feel free to contact:
1919
| ------------------------- |--------------------------------------------------- | --------------- |
2020
| **Conntracker** | Kernel space component that tracks connections inside the cluster using TC hook and classifier. Intercepts Ingress and Egress connections by registering a PerfEventArray with five parameters (Source Ip, Source Port, Destination Ip, Destination Port, Hash ID). The hash ID is generated to uniquely track the connection based on the previous 4 parameters | - [[92]](https://github.com/CortexFlow/CortexBrain/issues/92) <br> - [Core](https://github.com/CortexFlow/CortexBrain/milestone/1)
2121
| **Identity** | User Space program that uses Conntracker component and displays active connections in the cluster | - [[92]](https://github.com/CortexFlow/CortexBrain/issues/92) <br> - [Core](https://github.com/CortexFlow/CortexBrain/milestone/1)
22+
| **Metrics_tracer** | Kernel Space program that collects the main CortexBrain metrics collectors | - [[91]](https://github.com/CortexFlow/CortexBrain/issues/78) <br> - [Core](https://github.com/CortexFlow/CortexBrain/milestone/1)
23+
| **Metrics** | User Space implementation of the metrics_tracer BPF scripts. The metrics crate also aggregates, stores, and hosts the main data processing functions | - [[91]](https://github.com/CortexFlow/CortexBrain/issues/78) <br> - [Core](https://github.com/CortexFlow/CortexBrain/milestone/1)
2224
| **Loadbalancer** | User space component. One of the core functionalities. The load balancer uses XDP, Maps, and Identity to distribute traffic across multiple backends in the cluster using optimized load balancing techniques | - [[91]](https://github.com/CortexFlow/CortexBrain/issues/91) <br> - [[Core]](https://github.com/CortexFlow/CortexBrain/milestone/1)
2325
| **Maps** | Contains all the BPF maps used in the XDP component | /
2426
| **XDP** | Kernel Space program that operates in the XDP hook to filter traffic and apply access policies in the cluster | - [[91]](https://github.com/CortexFlow/CortexBrain/issues/91) <br> - [Core](https://github.com/CortexFlow/CortexBrain/milestone/1)

core/src/components/conntracker/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ pub fn try_veth_tracer(ctx: ProbeContext, mode: u8) -> Result<u32, i64> {
214214

215215
Ok(0)
216216
}
217-
218217
#[classifier]
219218
pub fn identity_classifier(ctx: TcContext) -> i32 {
220219
match try_identity_classifier(ctx) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "metrics"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
aya = "0.13.1"
8+
aya-log = "0.2.1"
9+
bytes = "1.4"
10+
tokio = { version = "1", features = ["full"] }
11+
anyhow = "1.0"
12+
tracing = "0.1.41"
13+
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
14+
libc = "0.2.172"
15+
bytemuck = "1.23.0"
16+
nix ={version="0.30.1",features=["net"]}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Phase 1: Build image
2+
FROM rust:1.85 AS builder
3+
4+
# Set working directory
5+
WORKDIR /usr/src/app/metrics
6+
7+
# Copy Cargo manifest and sources
8+
COPY Cargo.toml .
9+
COPY src ./src
10+
11+
# Fetch dependencies and build release
12+
RUN cargo fetch && cargo build --release
13+
14+
# Phase 2: Final minimal image
15+
FROM ubuntu:24.04
16+
17+
# Install runtime dependencies
18+
RUN apt-get update && apt-get install -y \
19+
ca-certificates \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
# Create working directory
23+
WORKDIR /usr/src/cortexbrain-metrics
24+
25+
# Copy the compiled binary
26+
COPY --from=builder /usr/src/app/metrics/target/release/metrics /usr/local/bin/cortexflow-metrics
27+
28+
# Copy configuration files
29+
COPY metrics_tracer /usr/src/cortexbrain-metrics/metrics_tracer
30+
31+
# Set environment variable
32+
ENV BPF_PATH="/usr/src/cortexbrain-metrics/metrics_tracer"
33+
34+
# Default command
35+
CMD ["cortexflow-metrics"]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
# Building identity files
4+
echo "Building the metrics-tracer files"
5+
pushd ../metrics_tracer
6+
./build-metrics-tracer.sh
7+
popd
8+
9+
echo "Copying metrics_tracer binaries"
10+
cp -r ../../../target/bpfel-unknown-none/release/metrics_tracer metrics_tracer
11+
12+
# Run docker build
13+
docker build -t metrics:0.0.1 .
14+
15+
# Cleanup
16+
echo "Cleaning building files"
17+
rm -rf metrics_tracer
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use aya::{
2+
Ebpf,
3+
maps::{
4+
Map, MapData,
5+
perf::{PerfEventArray, PerfEventArrayBuffer},
6+
},
7+
programs::{KProbe, SchedClassifier, TcAttachType, tc::SchedClassifierLinkId},
8+
util::online_cpus,
9+
};
10+
11+
use aya_log::EbpfLogger;
12+
use bytes::BytesMut;
13+
use std::{
14+
convert::TryInto,
15+
env, fs,
16+
net::Ipv4Addr,
17+
path::Path,
18+
sync::{
19+
Arc, Mutex,
20+
atomic::{AtomicBool, Ordering},
21+
},
22+
};
23+
24+
use anyhow::{Context, Ok};
25+
use tokio::{signal, sync::broadcast::error};
26+
use tracing::{error, info, warn};
27+
use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan};
28+
29+
const BPF_PATH: &str = "BPF_PATH"; //BPF env path
30+
use std::collections::HashMap;
31+
32+
#[repr(C)]
33+
#[derive(Clone, Copy)]
34+
struct NetworkMetrics {
35+
src_addr: u32,
36+
}
37+
38+
#[tokio::main]
39+
async fn main() -> Result<(), anyhow::Error> {
40+
//init tracing subscriber
41+
tracing_subscriber::fmt()
42+
.with_max_level(tracing::Level::INFO)
43+
.with_target(false)
44+
.with_level(true)
45+
.with_span_events(FmtSpan::NONE)
46+
.with_file(false)
47+
.pretty()
48+
.with_env_filter(EnvFilter::new("info"))
49+
.with_line_number(false)
50+
.init();
51+
52+
info!("Starting metrics service...");
53+
info!("fetching data");
54+
55+
let bpf_path = env::var(BPF_PATH).context("BPF_PATH environment variable required")?;
56+
let data = fs::read(Path::new(&bpf_path)).context("Failed to load file from path")?;
57+
let mut bpf = Ebpf::load(&data)?;
58+
//init bpf logger
59+
info!("Running Ebpf logger");
60+
info!("loading programs");
61+
let net_metrics_map = bpf
62+
.take_map("net_metrics")
63+
.ok_or_else(|| anyhow::anyhow!("net_metrics map not found"))?;
64+
65+
let program: &mut KProbe = bpf
66+
.program_mut("metrics_tracer")
67+
.ok_or_else(|| anyhow::anyhow!("program 'metrics_tracer' not found"))?
68+
.try_into()
69+
.context("Failed to init Kprobe program")?;
70+
71+
program
72+
.load()
73+
.context("Failed to load metrics_tracer program")?;
74+
75+
match program.attach("tcp_identify_packet_loss", 0) {
76+
std::result::Result::Ok(_) => {
77+
info!("program attacched successfully to the tcp_identify_packet_loss kprobe ")
78+
}
79+
Err(e) => error!(
80+
"An error occured while attaching the program to the tcp_identify_packet_loss kprobe. {:?} ",
81+
e
82+
),
83+
}
84+
let mut net_perf_buffer: Vec<PerfEventArrayBuffer<MapData>> = Vec::new();
85+
let mut net_perf_array: PerfEventArray<MapData> = PerfEventArray::try_from(net_metrics_map)?;
86+
87+
for cpu_id in online_cpus().map_err(|e| anyhow::anyhow!("Error {:?}", e))? {
88+
let buf: PerfEventArrayBuffer<MapData> = net_perf_array.open(cpu_id, None)?;
89+
net_perf_buffer.push(buf);
90+
}
91+
let running = AtomicBool::new(true);
92+
93+
let buffers = vec![BytesMut::with_capacity(1024); 10];
94+
95+
96+
tokio::spawn(async move{
97+
display_metrics_map(net_perf_buffer, running, buffers).await;
98+
});
99+
100+
101+
signal::ctrl_c().await?;
102+
Ok(())
103+
}
104+
105+
pub async fn display_metrics_map(
106+
mut perf_buffers: Vec<PerfEventArrayBuffer<MapData>>,
107+
running: AtomicBool,
108+
mut buffers: Vec<BytesMut>,
109+
) {
110+
while running.load(Ordering::SeqCst) {
111+
for buf in perf_buffers.iter_mut() {
112+
match buf.read_events(&mut buffers) {
113+
std::result::Result::Ok(events) => {
114+
for i in 0..events.read {
115+
let data = &buffers[i];
116+
if data.len() >= std::mem::size_of::<NetworkMetrics>() {
117+
let net_metrics: NetworkMetrics =
118+
unsafe { std::ptr::read(data.as_ptr() as *const _) };
119+
let src = Ipv4Addr::from(u32::from_be(net_metrics.src_addr));
120+
121+
info!("Detected packet loss SRC: {}", src);
122+
}
123+
}
124+
}
125+
Err(e) => {
126+
error!("Error reading events: {:?}", e);
127+
}
128+
}
129+
}
130+
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
131+
}
132+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[package]
2+
name = "metrics_tracer"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
aya-ebpf = { git = "https://github.com/aya-rs/aya" }
8+
aya-log-ebpf = { git = "https://github.com/aya-rs/aya" }
9+
bytemuck = {version ="1.23.0",features = ["derive"]}
10+
network-types = "0.0.8"
11+
12+
[build-dependencies]
13+
which = { version = "7.0.0", default-features = false }
14+
15+
[[bin]]
16+
name = "metrics_tracer"
17+
path = "src/main.rs"
18+
19+
[profile.dev]
20+
panic = "abort"
21+
22+
[profile.release]
23+
panic = "abort"
24+
25+
[target.bpfel-unknown-none]
26+
linker = "bpf-linker"
27+
rustflags = [
28+
"-C", "panic=abort",
29+
"-C", "target-feature=+alu32",
30+
"-C", "link-args=-znotext",
31+
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
echo "🚀 Building metrics tracer"
2+
3+
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
4+
5+
if [ $? -ne 0 ]; then
6+
echo "Error: Failed to dump BTF from vmlinux. Ensure bpftool is installed and has access to the kernel BTF."
7+
exit 1
8+
fi
9+
10+
if ! command -v bindgen &> /dev/null; then
11+
echo "bindgen not found, installing..."
12+
cargo install bindgen-cli
13+
export PATH="$HOME/.cargo/bin:$PATH" #add the ./cargo/bin directory to the PATH env variable
14+
fi
15+
16+
bindgen vmlinux.h -o src/bindings.rs --use-core --allowlist-type 'sk_buff'
17+
18+
cargo +nightly build -Z build-std=core --target bpfel-unknown-none --release --bin metrics_tracer
19+
20+
rm -f vmlinux.h

0 commit comments

Comments
 (0)