use std::collections::HashMap;
use std::rc::Rc;
pub mod ipc;
pub mod lang;
pub mod serialize;
pub mod test_helper;
#[macro_use]
pub mod algs;
mod errors;
pub use crate::errors::*;
pub use portus_export::register_ccp_alg;
use crate::ipc::BackendSender;
use crate::ipc::Ipc;
use crate::lang::{Reg, Scope};
pub trait DatapathTrait {
fn get_sock_id(&self) -> u32;
fn set_program(
&mut self,
program_name: &'static str,
fields: Option<&[(&str, u32)]>,
) -> Result<Scope>;
fn update_field(&self, sc: &Scope, update: &[(&str, u32)]) -> Result<()>;
}
#[derive(Clone)]
pub struct Datapath<T: Ipc> {
sock_id: u32,
sender: BackendSender<T>,
programs: Rc<HashMap<String, Scope>>,
}
impl<T: Ipc> DatapathTrait for Datapath<T> {
fn get_sock_id(&self) -> u32 {
self.sock_id
}
fn set_program(
&mut self,
program_name: &'static str,
fields: Option<&[(&str, u32)]>,
) -> Result<Scope> {
match self.programs.get(program_name) {
Some(sc) => {
let fields: Vec<(Reg, u64)> = fields
.unwrap_or_else(|| &[])
.iter()
.map(|&(reg_name, new_value)| {
if reg_name.starts_with("__") {
return Err(Error(format!(
"Cannot update reserved field: {:?}",
reg_name
)));
}
sc.get(reg_name)
.ok_or_else(|| Error(format!("Unknown field: {:?}", reg_name)))
.and_then(|reg| match *reg {
Reg::Control(idx, ref t, v) => {
Ok((Reg::Control(idx, t.clone(), v), u64::from(new_value)))
}
Reg::Implicit(idx, ref t) if idx == 4 || idx == 5 => {
Ok((Reg::Implicit(idx, t.clone()), u64::from(new_value)))
}
_ => Err(Error(format!("Cannot update field: {:?}", reg_name))),
})
})
.collect::<Result<_>>()?;
let msg = serialize::changeprog::Msg {
sid: self.sock_id,
program_uid: sc.program_uid,
num_fields: fields.len() as u32,
fields,
};
let buf = serialize::serialize(&msg)?;
self.sender.send_msg(&buf[..])?;
Ok(sc.clone())
}
_ => Err(Error(format!(
"Map does not contain datapath program with key: {:?}",
program_name
))),
}
}
fn update_field(&self, sc: &Scope, update: &[(&str, u32)]) -> Result<()> {
let fields: Vec<(Reg, u64)> = update
.iter()
.map(|&(reg_name, new_value)| {
if reg_name.starts_with("__") {
return Err(Error(format!(
"Cannot update reserved field: {:?}",
reg_name
)));
}
sc.get(reg_name)
.ok_or_else(|| Error(format!("Unknown field: {:?}", reg_name)))
.and_then(|reg| match *reg {
Reg::Control(idx, ref t, v) => {
Ok((Reg::Control(idx, t.clone(), v), u64::from(new_value)))
}
Reg::Implicit(idx, ref t) if idx == 4 || idx == 5 => {
Ok((Reg::Implicit(idx, t.clone()), u64::from(new_value)))
}
_ => Err(Error(format!("Cannot update field: {:?}", reg_name))),
})
})
.collect::<Result<_>>()?;
let msg = serialize::update_field::Msg {
sid: self.sock_id,
num_fields: fields.len() as u8,
fields,
};
let buf = serialize::serialize(&msg)?;
self.sender.send_msg(&buf[..])?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct DatapathInfo {
pub sock_id: u32,
pub init_cwnd: u32,
pub mss: u32,
pub src_ip: u32,
pub src_port: u32,
pub dst_ip: u32,
pub dst_port: u32,
}
pub struct Report {
pub program_uid: u32,
pub from: String,
fields: Vec<u64>,
}
impl Report {
pub fn get_field(&self, field: &str, sc: &Scope) -> Result<u64> {
if sc.program_uid != self.program_uid {
return Err(Error::from(StaleProgramError));
}
match sc.get(field) {
Some(r) => match *r {
Reg::Report(idx, _, _) => {
if idx as usize >= self.fields.len() {
Err(Error::from(InvalidReportError))
} else {
Ok(self.fields[idx as usize])
}
}
_ => Err(Error::from(InvalidRegTypeError)),
},
None => Err(Error::from(FieldNotFoundError)),
}
}
}
pub trait Flow {
fn on_report(&mut self, sock_id: u32, m: Report);
fn close(&mut self) {}
}
impl<T> Flow for Box<T>
where
T: Flow + ?Sized,
{
fn on_report(&mut self, sock_id: u32, m: Report) {
T::on_report(self, sock_id, m)
}
fn close(&mut self) {
T::close(self)
}
}
pub trait CongAlg<I: Ipc> {
type Flow: Flow;
fn name() -> &'static str;
fn datapath_programs(&self) -> HashMap<&'static str, String>;
fn new_flow(&self, control: Datapath<I>, info: DatapathInfo) -> Self::Flow;
}
mod run;
pub use run::*;
#[cfg(test)]
mod test;