Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ jobs:
- name: Install cargo-nextest
uses: taiki-e/install-action@nextest

- name: Run tests (all features, excluding msg-sim)
run: cargo nextest run --all --all-features --no-fail-fast --exclude msg-sim
- name: Run tests (all features, excluding linkem)
run: cargo nextest run --all --all-features --no-fail-fast --exclude linkem

- name: Run doc tests (excluding msg-sim)
- name: Run doc tests (excluding linkem)
run: cargo test --doc --all --all-features

# msg-sim tests require root privileges to create network namespaces
cargo-tests-msg-sim:
# linkem tests require root privileges to create network namespaces
cargo-tests-linkem:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
Expand All @@ -59,8 +59,8 @@ jobs:
- name: Install cargo-nextest
uses: taiki-e/install-action@nextest

- name: Run msg-sim tests (requires root for network namespaces)
run: sudo env "PATH=$PATH" "HOME=$HOME" cargo nextest run -p msg-sim --all-features --no-fail-fast --test-threads=1
- name: Run linkem tests (requires root for network namespaces)
run: sudo env "PATH=$PATH" "HOME=$HOME" cargo nextest run -p linkem --all-features --no-fail-fast --test-threads=1

cargo-lint:
runs-on: ubuntu-latest
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ cargo flamegraph --bin example_name
- **`msg-transport/`** - Transport layer (TCP, QUIC, IPC with pluggable trait design)
- **`msg-wire/`** - Wire protocol (authentication, compression: gzip/lz4/snappy/zstd)
- **`msg-common/`** - Shared utilities (channels, task management, time utils)
- **`msg-sim/`** - Network simulation on Linux, powered by rtnetlink.
- **`linkem/`** - Network emulation on Linux, powered by rtnetlink.

### Key Design Patterns
- **Trait-based extensibility** - Transport, ConnectionHook traits for pluggability
Expand All @@ -69,7 +69,7 @@ cargo flamegraph --bin example_name
- **debug-maxperf** - Performance with debug symbols

### Platform-Specific Features
- **Linux**: JeMalloc integration for memory performance and `msg-sim` support
- **Linux**: JeMalloc integration for memory performance and `linkem` support
- **MSRV**: Rust 1.86

## Testing Architecture
Expand All @@ -81,7 +81,7 @@ cargo flamegraph --bin example_name
- **Benchmarks** - Criterion-based in `msg/benches/`

### Network Simulation Testing
- Use `msg-sim` crate for chaos testing under various network conditions
- Use `linkem` crate for chaos testing under various network conditions
- Supports latency injection, bandwidth limiting, packet loss simulation

## Documentation Structure
Expand Down
30 changes: 15 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ members = [
"msg-wire",
"msg-transport",
"msg-common",
"msg-sim",
"linkem",
]
resolver = "2"

Expand Down Expand Up @@ -39,7 +39,7 @@ msg-wire = { path = "./msg-wire" }
msg-socket = { path = "./msg-socket" }
msg-transport = { path = "./msg-transport" }
msg-common = { path = "./msg-common" }
# msg-sim = { path = "./msg-sim" }
# linkem = { path = "./linkem" }

# async
async-trait = "0.1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The 📖 [MSG-RS Book][book] contains detailed information on how to use the lib

## MSRV

The minimum supported Rust version is 1.88 (see [rust-toolchain.toml](./rust-toolchain.toml)).
The minimum supported Rust version is 1.89.0 (see [rust-toolchain.toml](./rust-toolchain.toml)).

## Contributions & Bug Reports

Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ fmt:
# cargo nextest run --workspace --all-features --retries 3

test:
cargo nextest run --workspace --all-features --retries 3 -E 'not (package(msg-sim))'
cargo nextest run --workspace --all-features --retries 3 -E 'not (package(linkem))'
2 changes: 1 addition & 1 deletion msg-sim/Cargo.toml → linkem/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "msg-sim"
name = "linkem"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand Down
10 changes: 5 additions & 5 deletions msg-sim/README.md → linkem/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `msg-sim`
# `linkem`

In-process network emulation for Linux, powered by `rtnetlink`.

Expand All @@ -11,9 +11,9 @@ traffic control.
Each peer runs in an isolated network namespace, connected through a central hub:

```text
Hub Namespace (msg-sim-hub)
Hub Namespace (linkem-hub)
┌─────────────────────────────────────────────────────────────┐
│ Bridge (msg-sim-br0) │
│ Bridge (linkem-br0) │
└─────────┬───────────────────┬───────────────────┬───────────┘
│ │ │
veth pair veth pair veth pair
Expand All @@ -38,7 +38,7 @@ See [`src/network.rs`](src/network.rs) for detailed architecture documentation.
## Quick Example

```rust
use msg_sim::{network::{Network, Link}, tc::impairment::LinkImpairment, ip::Subnet};
use linkem::{network::{Network, Link}, tc::impairment::LinkImpairment, ip::Subnet};
use std::net::Ipv4Addr;

#[tokio::main]
Expand Down Expand Up @@ -99,7 +99,7 @@ See [`LinkImpairment::duplicate`](src/tc/impairment.rs) for details.
Tests require root privileges to create network namespaces:

```bash
sudo env "PATH=$PATH" "HOME=$HOME" cargo test -p msg-sim --all-features -- --test-threads=1
sudo env "PATH=$PATH" "HOME=$HOME" cargo test -p linkem --all-features -- --test-threads=1
```

The `--test-threads=1` flag is recommended to avoid conflicts between concurrent namespace operations.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! - Window scaling allows rwnd > 64KB (required for high-BDP links)
//!
//! ```bash
//! sudo HOME=$HOME $(which cargo) run --example bdp_throughput -p msg-sim
//! sudo HOME=$HOME $(which cargo) run --example bdp_throughput -p linkem
//! ```

#[cfg(not(target_os = "linux"))]
Expand All @@ -22,7 +22,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
};

use futures::StreamExt;
use msg_sim::{
use linkem::{
ip::Subnet,
network::{Link, Network, PeerIdExt},
tc::impairment::LinkImpairment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! # Running
//!
//! ```bash
//! sudo HOME=$HOME RUST_LOG=info $(which cargo) run --example multi_region -p msg-sim
//! sudo HOME=$HOME RUST_LOG=info $(which cargo) run --example multi_region -p linkem
//! ```

#[cfg(not(target_os = "linux"))]
Expand All @@ -30,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
time::{Duration, Instant},
};

use msg_sim::{
use linkem::{
ip::Subnet,
network::{Link, Network, PeerIdExt},
};
Expand All @@ -54,7 +54,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

/// Network impairment profiles based on typical cloud latencies.
mod profiles {
use msg_sim::tc::impairment::LinkImpairment;
use linkem::tc::impairment::LinkImpairment;

// US-East-1 <-> US-East-2: Same region, very fast
pub fn same_region() -> LinkImpairment {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Shows that each network namespace has isolated TCP sysctl parameters.
//!
//! ```bash
//! sudo HOME=$HOME RUST_LOG=info $(which cargo) run --example tcp_tuning -p msg-sim
//! sudo HOME=$HOME RUST_LOG=info $(which cargo) run --example tcp_tuning -p linkem
//! ```

#[cfg(not(target_os = "linux"))]
Expand All @@ -14,7 +14,7 @@ fn main() {}
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::net::{IpAddr, Ipv4Addr};

use msg_sim::{ip::Subnet, network::Network};
use linkem::{ip::Subnet, network::Network};
use tracing_subscriber::EnvFilter;

const TCP_RMEM: &str = "/proc/sys/net/ipv4/tcp_rmem";
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions msg-sim/src/dynch.rs → linkem/src/dynch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub trait Cast: Send + 'static {
/// # Example
///
/// ```
/// use msg_sim::dynch::{Cast, AnyCast};
/// use linkem::dynch::{Cast, AnyCast};
///
/// let original: i32 = 42;
/// let erased = AnyCast::erase(original);
Expand Down Expand Up @@ -179,7 +179,7 @@ impl<Ctx, C: Cast> DynRequestSender<Ctx, C> {
/// # Example
///
/// ```
/// use msg_sim::dynch::DynCh;
/// use linkem::dynch::DynCh;
///
/// #[derive(Default)]
/// struct Ctx {
Expand Down Expand Up @@ -249,7 +249,7 @@ impl<Ctx, C: Cast> DynRequestSender<Ctx, C> {
/// Using the default [`AnyCast`] strategy (most common):
///
/// ```
/// use msg_sim::dynch::DynCh;
/// use linkem::dynch::DynCh;
///
/// struct MyContext {
/// data: Vec<u8>,
Expand Down Expand Up @@ -277,7 +277,7 @@ impl<Ctx, C: Cast> DynCh<Ctx, C> {
/// # Example
///
/// ```
/// use msg_sim::dynch::DynCh;
/// use linkem::dynch::DynCh;
///
/// #[derive(Default)]
/// struct Ctx {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
36 changes: 18 additions & 18 deletions msg-sim/src/network.rs → linkem/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────────────────┐
//! │ Hub Namespace (msg-sim-hub) │
//! │ Hub Namespace (linkem-hub) │
//! │ │
//! │ ┌─────────────────────────────────────────────────────────────────────┐ │
//! │ │ Bridge (msg-sim-br0) │ │
//! │ │ Bridge (linkem-br0) │ │
//! │ │ │ │
//! │ │ Acts as a virtual switch connecting all peer veth endpoints │ │
//! │ └─────────────────────────────────────────────────────────────────────┘ │
Expand All @@ -29,7 +29,7 @@
//! │ msg-veth1 │ │ msg-veth2 │ │ msg-veth3 │
//! │ │ │ │ │ │
//! │ Peer 1 Namespace │ │ Peer 2 Namespace │ │ Peer 3 Namespace │
//! │ (msg-sim-1) │ │ (msg-sim-2) │ │ (msg-sim-3) │
//! │ (linkem-1) │ │ (linkem-2) │ │ (linkem-3) │
//! │ │ │ │ │ │
//! │ IP: 10.0.0.1 │ │ IP: 10.0.0.2 │ │ IP: 10.0.0.3 │
//! │ │ │ │ │ │
Expand Down Expand Up @@ -105,24 +105,24 @@ pub fn next_peer_id() -> PeerId {
pub type PeerId = usize;

/// Prefix for all network namespace names created by this crate.
pub const MSG_SIM_NAMESPACE_PREFIX: &str = "msg-sim";
pub const NAMESPACE_PREFIX: &str = "linkem";

/// Prefix for all virtual ethernet device names created by this crate.
pub const MSG_SIM_LINK_PREFIX: &str = "msg-veth";
pub const LINK_PREFIX: &str = "msg-veth";

/// Extension trait for peer IDs providing namespace and device naming utilities.
pub trait PeerIdExt: Display + Copy {
/// Get the network namespace name for this peer.
fn namespace_name(self) -> String {
format!("{MSG_SIM_NAMESPACE_PREFIX}-{self}")
format!("{NAMESPACE_PREFIX}-{self}")
}

/// Compute the IP address for this peer's veth device within the given subnet.
fn veth_address(self, subnet: Subnet) -> IpAddr;

/// Get the name of the veth device inside the peer's namespace.
fn veth_name(self) -> String {
format!("{MSG_SIM_LINK_PREFIX}{self}")
format!("{LINK_PREFIX}{self}")
}

/// Get the name of the veth device endpoint attached to the hub bridge.
Expand Down Expand Up @@ -353,9 +353,9 @@ pub type Result<T> = std::result::Result<T, Error>;
/// # Example
///
/// ```no_run
/// use msg_sim::network::{Network, Link, PeerOptions};
/// use msg_sim::tc::impairment::LinkImpairment;
/// use msg_sim::ip::Subnet;
/// use linkem::network::{Network, Link, PeerOptions};
/// use linkem::tc::impairment::LinkImpairment;
/// use linkem::ip::Subnet;
/// use std::net::Ipv4Addr;
///
/// #[tokio::main]
Expand Down Expand Up @@ -421,13 +421,13 @@ pub struct Network {

impl Network {
/// Name of the bridge device in the hub namespace.
const BRIDGE_NAME: &str = "msg-sim-br0";
const BRIDGE_NAME: &str = "linkem-br0";

/// Create a new simulated network with the given IP subnet.
///
/// This creates:
/// 1. A hub network namespace (`msg-sim-hub`)
/// 2. A bridge device (`msg-sim-br0`) in the hub namespace
/// 1. A hub network namespace (`linkem-hub`)
/// 2. A bridge device (`linkem-br0`) in the hub namespace
///
/// Peers can then be added with [`add_peer`](Self::add_peer).
pub async fn new(subnet: Subnet) -> Result<Self> {
Expand Down Expand Up @@ -475,7 +475,7 @@ impl Network {

/// Get the name of the hub namespace.
fn hub_namespace_name() -> String {
format!("{MSG_SIM_NAMESPACE_PREFIX}-hub")
format!("{NAMESPACE_PREFIX}-hub")
}

/// Add a new peer to the network.
Expand Down Expand Up @@ -632,8 +632,8 @@ impl Network {
/// # Example
///
/// ```no_run
/// use msg_sim::ip::Subnet;
/// use msg_sim::network::{Network, PeerOptions};
/// use linkem::ip::Subnet;
/// use linkem::network::{Network, PeerOptions};
/// use std::net::Ipv4Addr;
/// use tokio::net::TcpListener;
///
Expand Down Expand Up @@ -701,7 +701,7 @@ impl Network {
/// # Example
///
/// ```no_run
/// use msg_sim::{
/// use linkem::{
/// ip::Subnet,
/// network::{Link, Network, PeerOptions},
/// tc::impairment::LinkImpairment
Expand Down Expand Up @@ -826,7 +826,7 @@ impl Network {
}

#[cfg(test)]
mod msg_sim_network {
mod linkem_network {
use std::{
net::{Ipv4Addr, SocketAddr},
time::{Duration, Instant},
Expand Down
File renamed without changes.
Loading
Loading