A library for generating network emulation trace. Now only supported mahimahi.
Attention: This library is still under development. The API is not stable.
MSRV: 1.60
Use bandwidth model directly (model or bw-model feature should be enabled):
use netem_trace::model::{StaticBwConfig,NormalizedBwConfig};use netem_trace::{Bandwidth,Duration,BwTrace};letmut static_bw = StaticBwConfig::new().bw(Bandwidth::from_mbps(24)).duration(Duration::from_secs(1)).build();assert_eq!(
static_bw.next_bw(),Some((Bandwidth::from_mbps(24),Duration::from_secs(1))));letmut normal_bw = NormalizedBwConfig::new().mean(Bandwidth::from_mbps(12)).std_dev(Bandwidth::from_mbps(1)).duration(Duration::from_secs(1)).step(Duration::from_millis(100)).seed(42).build();assert_eq!(
normal_bw.next_bw(),Some((Bandwidth::from_bps(12069427),Duration::from_millis(100))));assert_eq!(
normal_bw.next_bw(),Some((Bandwidth::from_bps(12132938),Duration::from_millis(100))));letmut normal_bw = NormalizedBwConfig::new().mean(Bandwidth::from_mbps(12)).std_dev(Bandwidth::from_mbps(1)).duration(Duration::from_secs(1)).step(Duration::from_millis(100)).seed(42).upper_bound(Bandwidth::from_kbps(12100)).lower_bound(Bandwidth::from_kbps(11900)).build();assert_eq!(
normal_bw.next_bw(),Some((Bandwidth::from_bps(12069427),Duration::from_millis(100))));assert_eq!(
normal_bw.next_bw(),Some((Bandwidth::from_bps(12100000),Duration::from_millis(100))));Produce traces in mahimahi format (mahimahi feature should also be enabled):
use netem_trace::model::{StaticBwConfig};use netem_trace::{Bandwidth,Duration};use netem_trace::{Mahimahi,MahimahiExt};letmut static_bw = StaticBwConfig::new().bw(Bandwidth::from_mbps(24)).duration(Duration::from_secs(1)).build();assert_eq!(
static_bw.mahimahi(&Duration::from_millis(5)),[1,1,2,2,3,3,4,4,5,5]);letmut static_bw = StaticBwConfig::new().bw(Bandwidth::from_mbps(12)).duration(Duration::from_secs(1)).build();assert_eq!(
static_bw.mahimahi_to_string(&Duration::from_millis(5)),"1\n2\n3\n4\n5");let a = vec![Box::new(StaticBwConfig::new().bw(Bandwidth::from_mbps(12)).duration(Duration::from_secs(1)),)asBox<dyn BwTraceConfig>,Box::new(StaticBwConfig::new().bw(Bandwidth::from_mbps(24)).duration(Duration::from_secs(1)),)asBox<dyn BwTraceConfig>,];letmut c = Box::new(RepeatedBwPatternConfig::new().pattern(a).count(2)).into_model();assert_eq!(c.mahimahi(&Duration::from_millis(5)),[1,2,3,4,5]);Load traces in mahimahi format (mahimahi feature should also be enabled):
use netem_trace::load_mahimahi_trace;use netem_trace::{Bandwidth,BwTrace,Duration};let trace = vec![1,1,5,6];letmut bw = load_mahimahi_trace(trace,None).unwrap().build();// first cycleassert_eq!(
bw.next_bw(),Some((Bandwidth::from_mbps(24),Duration::from_millis(1))));assert_eq!(
bw.next_bw(),Some((Bandwidth::from_mbps(0),Duration::from_millis(3))));assert_eq!(
bw.next_bw(),Some((Bandwidth::from_mbps(12),Duration::from_millis(2))));// second cycleassert_eq!(
bw.next_bw(),Some((Bandwidth::from_mbps(24),Duration::from_millis(1))));Work with configuration files (serde feature should also be enabled):
use netem_trace::model::{StaticBwConfig,BwTraceConfig,RepeatedBwPatternConfig};use netem_trace::{Bandwidth,Duration,BwTrace};let a = vec![Box::new(StaticBwConfig::new().bw(Bandwidth::from_mbps(12)).duration(Duration::from_secs(1)),)asBox<dyn BwTraceConfig>,Box::new(StaticBwConfig::new().bw(Bandwidth::from_mbps(24)).duration(Duration::from_secs(1)),)asBox<dyn BwTraceConfig>,];let ser =
Box::new(RepeatedBwPatternConfig::new().pattern(a).count(2))asBox<dynBwTraceConfig>;let ser_str = serde_json::to_string(&ser).unwrap();let des_str = "{\"RepeatedBwPatternConfig\":{\"pattern\":[{\"StaticBwConfig\":{\"bw\":{\"gbps\":0,\"bps\":12000000},\"duration\":{\"secs\":1,\"nanos\":0}}},{\"StaticBwConfig\":{\"bw\":{\"gbps\":0,\"bps\":24000000},\"duration\":{\"secs\":1,\"nanos\":0}}}],\"count\":2}}";// The content would be "{\"RepeatedBwPatternConfig\":{\"pattern\":[{\"StaticBwConfig\":{\"bw\":\"12Mbps\",\"duration\":\"1s\"}},{\"StaticBwConfig\":{\"bw\":\"24Mbps\",\"duration\":\"1s\"}}],\"count\":2}}"// if the `human` feature is also enabled.assert_eq!(ser_str, des_str);let des:Box<dynBwTraceConfig> = serde_json::from_str(des_str).unwrap();letmut model = des.into_model();assert_eq!(
model.next_bw(),Some((Bandwidth::from_mbps(12),Duration::from_secs(1))));The series module (requires trace-ext feature) allows you to expand trace models into time series data for plotting and analysis.
use netem_trace::model::StaticBwConfig;use netem_trace::series::{expand_bw_trace, write_bw_series_json, write_bw_series_csv};use netem_trace::{Bandwidth,Duration};// Create and expand a traceletmut trace = StaticBwConfig::new().bw(Bandwidth::from_mbps(10)).duration(Duration::from_secs(5)).build();let series = expand_bw_trace(&mut trace,Duration::from_secs(0),Duration::from_secs(5));// Export to JSON or CSVwrite_bw_series_json(&series,"trace.json").unwrap();write_bw_series_csv(&series,"trace.csv").unwrap();- Bandwidth traces:
expand_bw_trace()→BwSeriesPoint(start_time, bandwidth, duration) - Delay traces:
expand_delay_trace()→DelaySeriesPoint(start_time, delay, duration) - Per-packet delay:
expand_delay_per_packet_trace()→DelayPerPacketSeriesPoint(packet_index, delay) - Loss/Duplicate traces:
expand_loss_trace(),expand_duplicate_trace()
JSON: Full structure with nested fields
[{"start_time": 0.0, "value": {"gbps": 0, "bps": 10000000}, "duration": 1.0}, ...]
CSV: Flat format for easy plotting
start_time_secs,bandwidth_bps,duration_secs0.0,10000000,1.0importjsonimportmatplotlib.pyplotaspltwithopen('trace.json') asf:
data=json.load(f)
times, bandwidths= [], []
forpointindata:
start=point['start_time']
duration=point['duration']
bw=point['value']['bps'] /1_000_000times.extend([start, start+duration])
bandwidths.extend([bw, bw])
plt.plot(times, bandwidths)
plt.xlabel('Time (s)')
plt.ylabel('Bandwidth (Mbps)')
plt.show()See examples/plot_traces.rs and examples/plot_example.py for complete examples. Run with:
cargo run --example plot_traces --features trace-extYou should follow our Code of Conduct.
See CONTRIBUTING GUIDELINES for contributing conventions.
Make sure to pass all the tests before submitting your code.
Yixin Shen | Haixuan Tong | Lethe Lee | Yixuan Gao | maxime-bruno |