83 lines
2.5 KiB
Rust
83 lines
2.5 KiB
Rust
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
|
//! xcu-ebpf-loader -- Cross-platform eBPF program loader
|
|
#![deny(warnings)]
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
#[derive(Debug)]
|
|
pub enum LoaderError {
|
|
FileNotFound(String),
|
|
ParseFailed(String),
|
|
ValidationFailed(String),
|
|
LoadFailed(String),
|
|
}
|
|
|
|
impl std::fmt::Display for LoaderError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::FileNotFound(e) => write!(f, "File not found: {e}"),
|
|
Self::ParseFailed(e) => write!(f, "Parse failed: {e}"),
|
|
Self::ValidationFailed(e) => write!(f, "Validation: {e}"),
|
|
Self::LoadFailed(e) => write!(f, "Load failed: {e}"),
|
|
}
|
|
}
|
|
}
|
|
impl std::error::Error for LoaderError {}
|
|
pub type Result<T> = std::result::Result<T, LoaderError>;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ProgramSpec {
|
|
pub name: String,
|
|
pub prog_type: String,
|
|
pub bytecode_path: String,
|
|
pub maps: Vec<String>,
|
|
}
|
|
|
|
pub struct ProgramLoader {
|
|
loaded: Arc<Mutex<HashMap<String, ProgramSpec>>>,
|
|
verified: Arc<Mutex<Vec<String>>>,
|
|
}
|
|
|
|
impl ProgramLoader {
|
|
pub fn new() -> Self {
|
|
Self { loaded: Arc::new(Mutex::new(HashMap::new())), verified: Arc::new(Mutex::new(Vec::new())) }
|
|
}
|
|
|
|
pub fn load_spec(&self, spec: ProgramSpec) -> Result<()> {
|
|
let mut loaded = self.loaded.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?;
|
|
loaded.insert(spec.name.clone(), spec);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn verify(&self, name: &str) -> Result<bool> {
|
|
let loaded = self.loaded.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?;
|
|
if !loaded.contains_key(name) { return Err(LoaderError::FileNotFound(name.into())); }
|
|
let mut verified = self.verified.lock().map_err(|e| LoaderError::LoadFailed(e.to_string()))?;
|
|
verified.push(name.to_string());
|
|
Ok(true)
|
|
}
|
|
|
|
pub fn loaded_count(&self) -> usize { self.loaded.lock().map(|l| l.len()).unwrap_or(0) }
|
|
}
|
|
|
|
impl Default for ProgramLoader {
|
|
fn default() -> Self { Self::new() }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
#[test]
|
|
fn test_loader() {
|
|
let loader = ProgramLoader::new();
|
|
loader.load_spec(ProgramSpec {
|
|
name: "test".into(), prog_type: "xdp".into(),
|
|
bytecode_path: "/dev/null".into(), maps: vec![],
|
|
}).unwrap();
|
|
assert_eq!(loader.loaded_count(), 1);
|
|
assert!(loader.verify("test").unwrap());
|
|
}
|
|
}
|