use super::error::{NetworkError, Result};
use std::process::Command;
pub struct Bridge {
pub name: String,
}
pub fn create_bridge(name: &str) -> Result<Bridge> {
if bridge_exists(name)? {
return Ok(Bridge {
name: name.to_string(),
});
}
let output = Command::new("ip")
.args(["link", "add", "name", name, "type", "bridge"])
.output()
.map_err(|e| NetworkError::Bridge(format!("Failed to execute ip command: {}", e)))?;
if !output.status.success() {
return Err(NetworkError::Bridge(format!(
"Failed to create bridge {}: {}",
name,
String::from_utf8_lossy(&output.stderr)
)));
}
let output = Command::new("ip")
.args(["link", "set", "dev", name, "mtu", "1500"])
.output()
.map_err(|e| NetworkError::Bridge(format!("Failed to set MTU: {}", e)))?;
if !output.status.success() {
return Err(NetworkError::Bridge(format!(
"Failed to set MTU for bridge {}: {}",
name,
String::from_utf8_lossy(&output.stderr)
)));
}
let output = Command::new("ip")
.args(["link", "set", "dev", name, "up"])
.output()
.map_err(|e| NetworkError::Bridge(format!("Failed to bring bridge up: {}", e)))?;
if !output.status.success() {
return Err(NetworkError::Bridge(format!(
"Failed to bring bridge {} up: {}",
name,
String::from_utf8_lossy(&output.stderr)
)));
}
Ok(Bridge {
name: name.to_string(),
})
}
pub fn bridge_exists(name: &str) -> Result<bool> {
use std::path::Path;
let bridge_path = format!("/sys/class/net/{}/bridge", name);
Ok(Path::new(&bridge_path).exists())
}
pub fn get_bridge(name: &str) -> Result<Bridge> {
if !bridge_exists(name)? {
return Err(NetworkError::NotFound(format!("Bridge {} not found", name)));
}
Ok(Bridge {
name: name.to_string(),
})
}
pub fn delete_bridge(name: &str) -> Result<()> {
if !bridge_exists(name)? {
return Ok(());
}
let output = Command::new("ip")
.args(["link", "delete", name])
.output()
.map_err(|e| NetworkError::Bridge(format!("Failed to delete bridge: {}", e)))?;
if !output.status.success() {
return Err(NetworkError::Bridge(format!(
"Failed to delete bridge {}: {}",
name,
String::from_utf8_lossy(&output.stderr)
)));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bridge_struct_creation() {
let bridge = Bridge {
name: "test_bridge".to_string(),
};
assert_eq!(bridge.name, "test_bridge");
}
#[test]
fn test_bridge_name_validation() {
let valid_names = vec!["br0", "bridge1", "my-bridge", "test_br"];
for name in valid_names {
let bridge = Bridge {
name: name.to_string(),
};
assert!(!bridge.name.is_empty());
}
}
}