Netsim - a crate for testing network-oriented code (call for feedback)

docs.rs, crates.io, github

For the last couple of months I've been developing this library through my work for MaidSafe as way of testing network-oriented Rust code. I'm posting it here in the hope that other people will find it useful and be able to provide feedback to help improve it.

netsim is a library that allows you to run functions in a network sandbox on virtual (TUN/TAP) interfaces. It's primarily intended for testing, so you can (for instance) have two tests which bind to the same port and run them in parallel without them interfering with each other. You can also inject/inspect raw packet data into the sandboxes, or run multiple sandboxes connected through a virtual network and add artificial latency, packet loss, network-address-translation, whatever.

Here's an example of sandboxing a closure and inspecting a UDP packet that it sends.

extern crate netsim;
extern crate tokio_core;
extern crate futures;

use std::net::UdpSocket;
use tokio_core::reactor::Core;
use futures::{Future, Stream};
use netsim::{spawn, node, Network, Ipv4Range};
use netsim::wire::Ipv4Payload;

// Create an event loop and a network to bind devices to.
let mut core = Core::new().unwrap();
let network = Network::new(&core.handle());
let handle = network.handle();

// Spawn a network with a single node - a machine with an IPv4 interface in the 10.0.0.0/8
// range, running the given callback.
let (spawn_complete, ipv4_plug) = spawn::ipv4_tree(
    &handle,
    Ipv4Range::local_subnet_10(),
    node::ipv4::machine(|ipv4_addr| {
        // Send a packet out the interface
        let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
        socket.send_to(b"hello world", "10.1.2.3:4567").unwrap();
    }),
);

let (packet_tx, packet_rx) = ipv4_plug.split();

// Inspect the packet sent out the interface.
core.run({
    packet_rx
    .into_future()
    .map(|(packet_opt, _)| {
        let packet = packet_opt.unwrap();
        match packet.payload() {
            Ipv4Payload::Udp(udp) => {
                assert_eq!(&udp.payload()[..], &b"hello world"[..]);
            },
            _ => panic!("unexpected payload"),
        }
    })
}).unwrap()

Note that this library is currently linux-only, but it's still been invaluable for us at MaidSafe for easily testing NAT-traversal code (for which it was originally developed) without having to use two people on the other ends of the real internet, behind real routers.

If you have any questions or feedback please post here or on the bug tracker :grin:

8 Likes

This is super useful man thanks! Hopefully will get a chance to use and provide feedback.

1 Like

Shameless bump. I'm also interested if people have any other uses for this other than testing.

1 Like