Skip to content

Commit

Permalink
return suitable string when error occur
Browse files Browse the repository at this point in the history
  • Loading branch information
junppyo committed Jun 7, 2023
1 parent 64745a9 commit 1042118
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 71 deletions.
94 changes: 64 additions & 30 deletions src/cbs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ pub fn get_linkspeed(ifname: &str) -> Result<String, String> {
let output = Command::new("ethtool").arg(ifname).output();
match output {
Ok(output) => {
let out = str::from_utf8(&output.stdout).unwrap();
let pattern = regex::Regex::new(r"Speed: (?P<speed>\d+(?:|k|M|G)b[p/]?s)").unwrap();
let matched = pattern.captures(out).unwrap();
Ok(matched.name("speed").unwrap().as_str().to_string())
let out = str::from_utf8(&output.stdout).expect("failed to parse cbs schedule");
let pattern = regex::Regex::new(r"Speed: (?P<speed>\d+(?:|k|M|G)b[p/]?s)")
.expect("failed to parse cbs schedule");
let matched = pattern.captures(out).expect("failed to parse cbs schedule");
Ok(matched
.name("speed")
.expect("failed to parse cbs schedule")
.as_str()
.to_string())
}
Err(e) => Err(e.to_string()),
}
Expand All @@ -42,12 +47,23 @@ pub fn to_bits(input: &Value) -> Result<i64, String> {
if let Some(value) = input.as_str() {
let matched =
regex::Regex::new(r"^(?P<v>[\d_]+)\s*(?P<modifier>|k|M|G|ki|Mi|Gi)(?P<b>b|B)$")
.unwrap()
.expect("failed to parse cbs schedule")
.captures(value)
.unwrap();
let v = matched.name("v").unwrap().as_str().parse::<i64>().unwrap();
let modifier = matched.name("modifier").unwrap().as_str();
let b = matched.name("b").unwrap().as_str();
.expect("failed to parse cbs schedule");
let v = matched
.name("v")
.expect("failed to parse cbs schedule")
.as_str()
.parse::<i64>()
.expect("failed to parse cbs schedule");
let modifier = matched
.name("modifier")
.expect("failed to parse cbs schedule")
.as_str();
let b = matched
.name("b")
.expect("failed to parse cbs schedule")
.as_str();
let multiplier_bits = match b {
"b" => 1,
"B" => 8,
Expand All @@ -65,17 +81,25 @@ pub fn to_bits(input: &Value) -> Result<i64, String> {
};
return Ok(v * multiplier_bits * multiplier_modifier);
}
Ok(input.as_i64().unwrap())
Ok(input.as_i64().expect("failed to parse cbs schedule"))
}

pub fn to_bps(input: &Value) -> Result<i64, String> {
if let Some(value) = input.as_str() {
let matched = regex::Regex::new(r"^(?P<v>[\d_]+)\s*(?P<modifier>|k|M|G)(?P<b>b|B)[p/]s$")
.unwrap()
.expect("failed to parse cbs schedule")
.captures(value)
.unwrap();
let v = matched.name("v").unwrap().as_str().parse::<i64>().unwrap();
let modifier = matched.name("modifier").unwrap().as_str();
.expect("failed to parse cbs schedule");
let v = matched
.name("v")
.expect("failed to parse cbs schedule")
.as_str()
.parse::<i64>()
.expect("failed to parse cbs schedule");
let modifier = matched
.name("modifier")
.expect("failed to parse cbs schedule")
.as_str();
return {
match modifier {
"" => Ok(v),
Expand All @@ -86,7 +110,7 @@ pub fn to_bps(input: &Value) -> Result<i64, String> {
}
};
}
Ok(input.as_i64().unwrap())
Ok(input.as_i64().expect("failed to parse cbs schedule"))
}

pub fn calc_credits(
Expand All @@ -95,7 +119,7 @@ pub fn calc_credits(
) -> (CbsCredit, CbsCredit) {
let mut idle_slope_a = 0;
let mut max_frame_a = 0;
for stream in streams.get(&'a').unwrap() {
for stream in streams.get(&'a').expect("failed to parse cbs schedule") {
idle_slope_a += stream.bandwidth;
max_frame_a += stream.max_frame;
}
Expand All @@ -111,7 +135,7 @@ pub fn calc_credits(

let mut idle_slope_b = 0;
let mut max_frame_b = 0;
for stream in streams.get(&'b').unwrap() {
for stream in streams.get(&'b').expect("failed to parse cbs schedule") {
idle_slope_b += stream.bandwidth;
max_frame_b += stream.max_frame;
}
Expand Down Expand Up @@ -144,40 +168,50 @@ pub fn normalise_cbs(ifname: &str, config: &Value) -> Result<CbsConfig, String>
Ok(speed) => to_bps(&Value::String(speed))?,
Err(_) => 1_000_000_000, // 1000Mbps
};
for (prio, priomap) in config.as_mapping().unwrap() {
if !tc_map.contains_key(&prio.as_i64().unwrap()) {
tc_map.insert(prio.as_i64().unwrap(), tc_map.len() as i64);
for (prio, priomap) in config.as_mapping().expect("failed to parse cbs schedule") {
if !tc_map.contains_key(&prio.as_i64().expect("failed to parse cbs schedule")) {
tc_map.insert(
prio.as_i64().expect("failed to parse cbs schedule"),
tc_map.len() as i64,
);
}
let child = CbsChild {
prio: prio.as_i64().unwrap(),
prio: prio.as_i64().expect("failed to parse cbs schedule"),
max_frame: to_bits(
priomap
.get(&Value::String("max_frame".to_string()))
.unwrap(),
.expect("failed to parse cbs schedule"),
)?,
bandwidth: to_bps(
priomap
.get(&Value::String("bandwidth".to_string()))
.unwrap(),
.expect("failed to parse cbs schedule"),
)?,
};
let index = priomap
.get(Value::String("class".to_string()).as_str().unwrap())
.unwrap()
.get(
Value::String("class".to_string())
.as_str()
.expect("failed to parse cbs schedule"),
)
.expect("failed to parse cbs schedule")
.as_str()
.unwrap()
.expect("failed to parse cbs schedule")
.chars()
.next()
.unwrap();
streams.get_mut(&index).unwrap().push(child);
.expect("failed to parse cbs schedule");
streams
.get_mut(&index)
.expect("failed to parse cbs schedule")
.push(child);
}
tc_map.insert(-1, tc_map.len() as i64);
let num_tc = tc_map.len() as i64;
for i in 0..16 {
if tc_map.contains_key(&i) {
ret_map.insert(i, *tc_map.get(&i).unwrap());
ret_map.insert(i, *tc_map.get(&i).expect("failed to parse cbs schedule"));
} else {
ret_map.insert(i, *tc_map.get(&-1).unwrap());
ret_map.insert(i, *tc_map.get(&-1).expect("failed to parse cbs schedule"));
}
}
let (credits_a, credits_b) = calc_credits(&streams, linkspeed);
Expand Down
41 changes: 23 additions & 18 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::tas::{normalise_tas, TasConfig};
use serde_yaml::{self, Value};
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::io::{BufReader, Error};
use std::str;

#[derive(Clone)]
Expand All @@ -25,46 +25,52 @@ impl Config {

pub fn normalise_vlan(input: &Value) -> HashMap<i64, HashMap<i64, i64>> {
let mut ret_map = HashMap::new();
for (valnid, prio) in input.as_mapping().unwrap() {
for (vlanid, prio) in input.as_mapping().expect("failed to parse vlan") {
let mut vlan_map = HashMap::new();
for (prio, pri) in prio.as_mapping().unwrap() {
vlan_map.insert(prio.as_i64().unwrap(), pri.as_i64().unwrap());
for (prio, pri) in prio.as_mapping().expect("failed to parse vlan") {
vlan_map.insert(
prio.as_i64().expect("failed to parse vlan"),
pri.as_i64().expect("failed to parse vlan"),
);
}
ret_map.insert(valnid.as_i64().unwrap(), vlan_map);
ret_map.insert(vlanid.as_i64().expect("failed to parse vlan"), vlan_map);
}
ret_map
}

pub fn read_config(config_path: &str) -> Result<HashMap<String, Config>, i64> {
let file = File::open(config_path).expect("failed to open config.yaml");
pub fn read_config(config_path: &str) -> Result<HashMap<String, Config>, String> {
let file = File::open(config_path)
.unwrap_or_else(|_| panic!("failed to open config.yaml: {}", Error::last_os_error()));
let reader = BufReader::new(file);
let config: Value = serde_yaml::from_reader(reader).expect("failed to parse YAML");
let config: Value = serde_yaml::from_reader(reader)
.unwrap_or_else(|_| panic!("failed to parse YAML: {}", Error::last_os_error()));
let config = config
.as_mapping()
.unwrap()
.expect("failed to parse config")
.get(&Value::String("nics".to_string()))
.unwrap()
.unwrap_or_else(|| panic!("failed to parse config: {}", Error::last_os_error()))
.as_mapping()
.unwrap();
.expect("failed to parse config");
let mut ifname;
let mut ret = HashMap::new();
for (key, value) in config {
let mut info = Config::new(HashMap::new());
let value = value.as_mapping().unwrap();
ifname = key.as_str().unwrap();
let value = value.as_mapping().expect("failed to parse config");
ifname = key.as_str().expect("failed to parse config");
if value.contains_key(&Value::String("egress-qos-map".to_string())) {
info.egress_qos_map = normalise_vlan(
value
.get(&Value::String("egress-qos-map".to_string()))
.unwrap(),
.expect("failed to parse config"),
);
} else {
return Err(format!("egress-qos-map is not defined for {}", ifname));
}
if value.contains_key(&Value::String("tas".to_string())) {
match normalise_tas(value.get(&Value::String("tas".to_string())).unwrap()) {
Ok(tas) => info.tas = Some(tas),
Err(e) => {
eprintln!("{}", e);
return Err(-1);
return Err(e);
}
}
}
Expand All @@ -75,8 +81,7 @@ pub fn read_config(config_path: &str) -> Result<HashMap<String, Config>, i64> {
) {
Ok(cbs) => info.cbs = Some(cbs),
Err(e) => {
eprintln!("{}", e);
return Err(-1);
return Err(e);
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn create_vlan(ifname: &str, vlanid: u16) -> Result<String, String> {
unlock_shmem(&shm_fd)?;
match result {
Ok(_) => Ok(name),
Err(_) => Err(format!("Create vlan fails {}", Error::last_os_error())),
Err(e) => Err(format!("Create vlan fails {}", e)),
}
}

Expand All @@ -108,7 +108,7 @@ fn delete_vlan(ifname: &str, vlanid: u16) -> Result<i32, String> {
}
match vlan::delete_vlan(ifname, vlanid) {
Ok(v) => Ok(v),
Err(_) => Err(format!("Delete vlan fails {}", Error::last_os_error())),
Err(e) => Err(format!("Delete vlan fails {}", e)),
}
} else {
Ok(0)
Expand All @@ -125,8 +125,8 @@ pub fn sock_open(
) -> Result<TsnSocket, String> {
let name = match create_vlan(ifname, vlanid) {
Ok(v) => v,
Err(_) => {
return Err(format!("Create vlan fails {}", Error::last_os_error()));
Err(e) => {
return Err(format!("Create vlan fails {}", e));
}
};
let sock;
Expand Down Expand Up @@ -188,10 +188,10 @@ pub fn sock_open(
pub fn sock_close(sock: &mut TsnSocket) -> Result<(), String> {
match delete_vlan(&sock.ifname, sock.vlanid) {
Ok(_) => {
close(sock.fd).unwrap();
close(sock.fd).expect("close sock");
Ok(())
}
Err(_) => Err(format!("Delete vlan fails: {}", Error::last_os_error())),
Err(e) => Err(format!("Delete vlan fails: {}", e)),
}
}

Expand Down Expand Up @@ -569,7 +569,7 @@ fn get_config(ifname: &str) -> Result<config::Config, String> {
let configs = config::read_config(&config_path);
let configs = match configs {
Ok(v) => v,
Err(_) => return Err(format!("Read config fails: {}", Error::last_os_error())),
Err(e) => return Err(format!("Read config fails: {}", e)),
};
let config = configs.get(ifname);
match config {
Expand Down
20 changes: 12 additions & 8 deletions src/tas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,28 @@ pub fn normalise_tas(config: &Value) -> Result<TasConfig, String> {
let mut ret_map = HashMap::new();
let schedules = config
.get(&Value::String("schedule".to_string()))
.unwrap()
.expect("failed to parse tas schedule")
.as_sequence()
.unwrap();
.expect("failed to parse tas schedule");
for schedule in schedules {
let mut v = Vec::new();

for prio in schedule
.get(&Value::String("prio".to_string()))
.unwrap()
.expect("failed to parse tas schedule")
.as_sequence()
.unwrap()
.expect("failed to parse tas schedule")
{
v.push(prio.as_i64().unwrap());
v.push(prio.as_i64().expect("priority must be an integer"));
if prio.as_i64().unwrap() > 0 && !tc_map.contains_key(&prio.as_i64().unwrap()) {
tc_map.insert(prio.as_i64().unwrap(), tc_map.len() as i64);
}
}
let time = to_ns(schedule.get(&Value::String("time".to_string())).unwrap())?;
let time = to_ns(
schedule
.get(&Value::String("time".to_string()))
.expect("failed to parse tas schedule"),
)
.expect("tas schedule time must be in ns");
tas_schedule.push(TasSchedule { time, prio: v });
}

Expand Down Expand Up @@ -91,7 +95,7 @@ pub fn normalise_tas(config: &Value) -> Result<TasConfig, String> {
let txtime_delay = to_ns(
config
.get(&Value::String("txtime_delay".to_string()))
.unwrap(),
.expect("failed to parse tas schedule"),
)?;
Ok(TasConfig {
txtime_delay,
Expand Down
12 changes: 4 additions & 8 deletions src/vlan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,12 @@ pub fn setup_tas(ifname: &str, config: &TasConfig) -> Result<i32, String> {
sched_entries.push_str(&format!(" sched-entry {}", entry));
}
let cmd = format!(
"tc qdisc replace dev {} parent root handle {} taprio num_tc {} map{}
queues{} base-time {}{} flags 0x1 txtime-delay {} clockid CLOCK_TAI",
"tc qdisc replace dev {} parent root handle {} taprio num_tc {} map{} queues{} base-time {}{} flags 0x1 txtime-delay {} clockid CLOCK_TAI",
ifname, handle, num_tc, priomap, queues, base_time, sched_entries, txtime_delay
);
run_cmd(&cmd)?;
let cmd = format!(
"tc qdisc replace dev {} parent {}:1 etf clockid
CLOCK_TAI delta {} offload skip_sock_check",
"tc qdisc replace dev {} parent {}:1 etf clockid CLOCK_TAI delta {} offload skip_sock_check",
ifname, handle, txtime_delay
);
run_cmd(&cmd)?;
Expand All @@ -62,8 +60,7 @@ pub fn setup_cbs(ifname: &str, config: &CbsConfig) -> Result<i32, String> {
queues.push_str(&format!("{} ", s));
}
let cmd = format!(
"tc qdisc add dev {} parent root handle {} mqprio num_tc {} map\
{} queues {}hw 0",
"tc qdisc add dev {} parent root handle {} mqprio num_tc {} map {} queues {}hw 0",
ifname, root_handle, num_tc, priomap, queues
);
run_cmd(&cmd)?;
Expand All @@ -75,8 +72,7 @@ pub fn setup_cbs(ifname: &str, config: &CbsConfig) -> Result<i32, String> {
let hicredit = val.hicredit;
let locredit = val.locredit;
let cmd = format!(
"tc qdisc replace dev {} parent {}:{} handle {}
cbs idleslope {} sendslope {} hicredit {} locredit {} offload 1",
"tc qdisc replace dev {} parent {}:{} handle {} cbs idleslope {} sendslope {} hicredit {} locredit {} offload 1",
ifname, root_handle, qid, handle, idleslope, sendslope, hicredit, locredit
);
run_cmd(&cmd)?;
Expand Down

0 comments on commit 1042118

Please sign in to comment.