Skip to main content

Crate badnet

Crate badnet 

Source
Expand description

Simulate bad network conditions on loopback using tc-netem.

badnet provisions a pair of loopback addresses and wires them together through a Linux traffic-control (tc) pipeline so that any traffic sent from one address to the other passes through a configurable tc-netem qdisc. This lets you reproduce packet loss, corruption, duplication, delay, and reordering in ordinary integration tests without touching real network interfaces.

§Platform requirements

Linux only. The calling process needs CAP_NET_ADMIN. Grant it with setcap rather than running the whole process as root — running a test binary as root gives it unrestricted access to the entire system, which is far broader than what this library needs:

sudo setcap cap_net_admin+eip target/debug/deps/<test_binary>

§Quick start

use std::net::UdpSocket;
use std::time::Duration;
use badnet::BadNet;

// Create a link that drops 10 % of packets.
let net = BadNet::builder()
    .loss(0.10)
    .build()?;

// Bind sockets to the two ends and communicate normally.
let tx = UdpSocket::bind(format!("{}:0",   net.left_addr()))?;
let rx = UdpSocket::bind(format!("{}:9000", net.right_addr()))?;
rx.set_read_timeout(Some(Duration::from_millis(200)))?;

tx.send_to(b"hello", format!("{}:9000", net.right_addr()))?;
// … the link will drop ~10 % of these …

// The tc rules and loopback addresses are removed when `net` is dropped.

§Isolation

Each BadNet instance claims a unique address pair and HTB class, so multiple instances running concurrently do not interfere with each other.

§Reorder and gap

BadNetBuilder::reorder requires BadNetBuilder::delay to have been called first (enforced at compile time via the typestate on BadNetBuilder). BadNetBuilder::gap additionally requires BadNetBuilder::reorder.

use std::time::Duration;
use badnet::BadNet;

// 20 ms delay, 30 % of packets reordered probabilistically.
let net = BadNet::builder()
    .delay(Duration::from_millis(20))
    .reorder(0.30)
    .build()?;

// Every 5th packet reordered deterministically (reorder must be 1.0 for
// a fully deterministic pattern).
let net = BadNet::builder()
    .delay(Duration::from_millis(20))
    .reorder(1.0)
    .gap(5)
    .build()?;

§Reproducible impairment with seeds

tc-netem uses an internal PRNG to decide which packets to drop, corrupt, duplicate, or reorder. Passing the same seed on the same kernel version produces an identical sequence of decisions, making test failures reproducible:

use badnet::BadNet;

// Seed 42 produces the same loss decisions on every run.
let net = BadNet::builder().seed(42).loss(0.10).build()?;

The default seed is 0. Vary the seed when you want statistically independent runs rather than a fixed pattern.

Structs§

BadNet
A running virtual link backed by loopback addresses and tc-netem.
BadNetBuilder
Builder for a BadNet link.