Skip to content

stack-rs/netem-trace

netem-trace

github-repo crates.io docs.rs LICENSE Apache-2.0

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

Examples

Use bandwidth model directly (model or bw-model feature should be enabled):

use netem_trace::model::{StaticBwConfig, NormalizedBwConfig};
use netem_trace::{Bandwidth, Duration, BwTrace};
let mut 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)))
);
let mut 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)))
);
let mut 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};
let mut 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]
);
let mut 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)),
    ) as Box<dyn BwTraceConfig>,
    Box::new(
        StaticBwConfig::new()
            .bw(Bandwidth::from_mbps(24))
            .duration(Duration::from_secs(1)),
    ) as Box<dyn BwTraceConfig>,
];
let mut 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];
let mut bw = load_mahimahi_trace(trace, None).unwrap().build();
// first cycle
assert_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 cycle
assert_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)),
    ) as Box<dyn BwTraceConfig>,
    Box::new(
        StaticBwConfig::new()
            .bw(Bandwidth::from_mbps(24))
            .duration(Duration::from_secs(1)),
    ) as Box<dyn BwTraceConfig>,
];
let ser =
    Box::new(RepeatedBwPatternConfig::new().pattern(a).count(2)) as Box<dyn BwTraceConfig>;
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<dyn BwTraceConfig> = serde_json::from_str(des_str).unwrap();
let mut model = des.into_model();
assert_eq!(
    model.next_bw(),
    Some((Bandwidth::from_mbps(12), Duration::from_secs(1)))
);

Plotting and Visualization

The series module (requires trace-ext feature) allows you to expand trace models into time series data for plotting and analysis.

Quick Example

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 trace
let mut 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 CSV
write_bw_series_json(&series, "trace.json").unwrap();
write_bw_series_csv(&series, "trace.csv").unwrap();

Supported Trace Types

  • 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()

Export Formats

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_secs
0.0,10000000,1.0

Plotting in Python

import json
import matplotlib.pyplot as plt

with open('trace.json') as f:
    data = json.load(f)

times, bandwidths = [], []
for point in data:
    start = point['start_time']
    duration = point['duration']
    bw = point['value']['bps'] / 1_000_000
    times.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-ext

Maintainer

@BobAnkh

How to contribute

You should follow our Code of Conduct.

See CONTRIBUTING GUIDELINES for contributing conventions.

Make sure to pass all the tests before submitting your code.

Contributors

Yixin
Yixin Shen
Haixuan
Haixuan Tong
Lethe
Lethe Lee
Yixuan
Yixuan Gao
maxime-bruno/
maxime-bruno

LICENSE

Apache-2.0

About

A library for generating network emulation trace. Support Mahimahi.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 7

Languages