Skip to content

Commit 02e245c

Browse files
committed
feat(devices): add DuplicateDevice (#33)
1 parent 1e888d3 commit 02e245c

18 files changed

+6305
-1
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ ctrlc = "3.2.5"
1414
figment = { version = "0.10", features = ["toml", "env", "json"] }
1515
futures = "0.3.29"
1616
human-bandwidth = { version = "0.1.1", features = ["serde"] }
17-
netem-trace = { version = "0.3.3", features = ["serde", "human", "mahimahi"] }
17+
netem-trace = { version = "0.3.4", features = ["serde", "human", "mahimahi"] }
1818
nix = "0.26.2"
1919
once_cell = "1.19"
2020
rand = "0.8.5"

rattan-core/src/config/duplicate.rs

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use figment::{
2+
providers::{Format, Json, Toml},
3+
Figment,
4+
};
5+
use netem_trace::{model::DuplicateTraceConfig, DuplicatePattern, DuplicateTrace};
6+
use rand::{rngs::StdRng, SeedableRng};
7+
use serde::{Deserialize, Serialize};
8+
9+
use crate::{
10+
core::DeviceFactory,
11+
devices::{duplicate, Packet},
12+
error::Error,
13+
};
14+
15+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16+
#[derive(Debug, Clone)]
17+
pub struct DuplicateDeviceBuildConfig {
18+
pub pattern: DuplicatePattern,
19+
pub seed: Option<u64>,
20+
}
21+
22+
impl DuplicateDeviceBuildConfig {
23+
pub fn into_factory<P: Packet>(
24+
self,
25+
) -> impl DeviceFactory<duplicate::DuplicateDevice<P, StdRng>> {
26+
move |handle| {
27+
let _guard = handle.enter();
28+
let rng = StdRng::seed_from_u64(self.seed.unwrap_or(42));
29+
duplicate::DuplicateDevice::new(self.pattern, rng)
30+
}
31+
}
32+
}
33+
34+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35+
#[derive(Debug, Clone)]
36+
pub struct DuplicateReplayDeviceBuildConfig {
37+
pub trace: String,
38+
pub seed: Option<u64>,
39+
}
40+
41+
impl DuplicateReplayDeviceBuildConfig {
42+
fn get_trace(&self) -> Result<Box<dyn DuplicateTrace>, Error> {
43+
let file_path = std::path::Path::new(&self.trace);
44+
if let Some(ext) = file_path.extension() {
45+
if ext == "json" {
46+
let trace: Box<dyn DuplicateTraceConfig> = Figment::new()
47+
.merge(Json::file(file_path))
48+
.extract()
49+
.map_err(|e| Error::ConfigError(e.to_string()))?;
50+
return Ok(trace.into_model());
51+
} else if ext == "toml" {
52+
let trace: Box<dyn DuplicateTraceConfig> = Figment::new()
53+
.merge(Toml::file(file_path))
54+
.extract()
55+
.map_err(|e| Error::ConfigError(e.to_string()))?;
56+
return Ok(trace.into_model());
57+
}
58+
}
59+
Err(Error::ConfigError(format!(
60+
"Unknown trace file format: {:?}",
61+
file_path
62+
)))
63+
}
64+
65+
pub fn into_factory<P: Packet>(
66+
self,
67+
) -> impl DeviceFactory<duplicate::DuplicateReplayDevice<P, StdRng>> {
68+
move |handle| {
69+
let _guard = handle.enter();
70+
let trace = self.get_trace()?;
71+
let rng = StdRng::seed_from_u64(self.seed.unwrap_or(42));
72+
duplicate::DuplicateReplayDevice::new(trace, rng)
73+
}
74+
}
75+
}

rattan-core/src/config/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ use crate::control::http::HttpConfig;
1010

1111
mod bandwidth;
1212
mod delay;
13+
mod duplicate;
1314
mod loss;
1415

1516
pub use bandwidth::*;
1617
pub use delay::*;
18+
pub use duplicate::*;
1719
pub use loss::*;
1820

1921
/// Configuration for the whole Rattan system.
@@ -74,5 +76,7 @@ pub enum DeviceBuildConfig<P: Packet> {
7476
DelayReplay(DelayReplayDeviceBuildConfig),
7577
Loss(LossDeviceBuildConfig),
7678
LossReplay(LossReplayDeviceBuildConfig),
79+
Duplicate(DuplicateDeviceBuildConfig),
80+
DuplicateReplay(DuplicateReplayDeviceBuildConfig),
7781
Custom,
7882
}

0 commit comments

Comments
 (0)