badnet
Simulate bad network conditions in Rust integration tests using Linux tc-netem.
Each BadNet instance provisions a loopback address pair wired through a configurable netem qdisc. Traffic sent between the two addresses passes through the impairment rules. Everything is cleaned up when the handle is dropped.
Usage
use Duration;
use BadNet;
let net = builder
.seed // reproducible pattern across runs
.loss // 10% packet loss
.corrupt // 2% bit-flip (appears as loss at the socket layer)
.duplicate // 5% duplication
.delay
.reorder // 20% of packets skip the delay and arrive early
.build?;
// Bind sockets to the two ends and communicate normally.
let tx = bind?;
let rx = bind?;
reorder requires delay. gap (periodic deterministic reorder) requires both:
let net = builder
.delay
.reorder
.gap // every 5th packet is sent immediately
.build?;
Requirements
Linux only. Requires CAP_NET_ADMIN. Grant it with setcap or run as root:
Troubleshooting
Stale state after Ctrl-C or SIGKILL
BadNet cleans up TC rules and loopback addresses in its Drop implementation. If the process is killed before Drop runs, the next run will fail with errors like Exclusivity flag on or Address already assigned. To clean up manually:
; \
| | \
Ctrl-C in long-running binaries
Rust does not run destructors on SIGINT by default. Install a signal handler that calls std::process::exit (which does run destructors) to ensure cleanup on interrupt. The ctrlc crate makes this easy:
set_handler.unwrap;