Rust embedded network stack
Go to file
whitequark 250a84e513 Implement a Device that emits a stream in libpcap format. 2017-07-23 14:56:24 +00:00
examples Fix an off-by-three-orders-of-magnitude error. 2017-07-23 12:03:56 +00:00
fuzz Add packet parser fuzzer. 2017-06-24 11:43:12 +00:00
src Implement a Device that emits a stream in libpcap format. 2017-07-23 14:56:24 +00:00
.gitignore Implement a Device that emits a stream in libpcap format. 2017-07-23 14:56:24 +00:00
.travis.yml Travis: require build on stable Rust to succeed. 2017-06-29 16:09:01 +00:00
Cargo.toml Add a bare-metal usage example. 2017-07-14 03:18:11 +00:00
LICENSE-0BSD.txt Fix outdated info in README. 2016-12-28 00:27:49 +00:00
README.md Add a bare-metal usage example. 2017-07-14 03:18:11 +00:00

README.md

smoltcp

smoltcp is a standalone, event-driven TCP/IP stack that is designed for bare-metal, real-time systems. Its design goals are simplicity and robustness. Its design anti-goals include complicated compile-time computations, such as macro or type tricks, even at cost of performance degradation.

smoltcp does not need heap allocation at all, is extensively documented, and compiles on stable Rust 1.18 and later.

Features

smoltcp is missing many widely deployed features, whether by design or simply because no one implemented them yet. To set expectations right, both implemented and omitted features are listed.

Media layer

The only supported medium is Ethernet.

  • Regular Ethernet II frames are supported.
  • Unicast and broadcast packets are supported, multicast packets are not supported.
  • ARP packets (including gratuitous requests and replies) are supported.
  • 802.3 frames and 802.1Q are not supported.
  • Jumbo frames are not supported.

IP layer

The only supported internetworking protocol is IPv4.

  • IPv4 header checksum is supported.
  • IPv4 fragmentation is not supported.
  • IPv4 options are not supported.
  • ICMPv4 header checksum is supported.
  • ICMPv4 echo requests and replies are supported.
  • ICMPv4 destination unreachable message is supported.
  • ICMPv4 parameter problem message is not supported.

UDP layer

The UDP protocol is supported over IPv4.

  • UDP header checksum is supported.
  • UDP sockets are supported.

TCP layer

The TCP protocol is supported over IPv4. Server and client sockets are supported.

  • TCP header checksum is supported.
  • Multiple packets will be transmitted without waiting for an acknowledgement.
  • Lost packets will be retransmitted with exponential backoff, starting at a fixed delay of 100 ms.
  • After arriving at the TIME-WAIT state, sockets will close after a fixed delay of 10 s.
  • TCP urgent pointer is not supported; any urgent octets will be received alongside data octets.
  • Reassembly of out-of-order segments is not supported.
  • The status of TCP options is:
    • Maximum segment size option is supported.
    • Window scaling is not supported, and the maximum buffer size is 65536.
    • Timestamping is not supported.
    • Fast open is not supported.
  • Keepalive is not supported.

Installation

To use the smoltcp library in your project, add the following to Cargo.toml:

[dependencies]
smoltcp = "0.3"

The default configuration assumes a hosted environment, for ease of evaluation. You probably want to disable default features and configure them one by one:

[dependencies]
smoltcp = { version = "0.3", default-features = false, features = ["..."] }

Feature std

The std feature enables use of objects and slices owned by the networking stack through a dependency on std::boxed::Box and std::vec::Vec.

This feature is enabled by default.

Features raw_socket and tap_interface

Enable smoltcp::phy::RawSocket and smoltcp::phy::TapInterface, respectively.

These features are enabled by default.

Feature alloc

The alloc feature enables use of objects owned by the networking stack through a dependency on alloc::boxed::Box. This only works on nightly rustc.

Feature collections

The collections feature enables use of slices owned by the networking stack through a dependency on collections::vec::Vec. This only works on nightly rustc.

Feature log

The log feature enables logging of events within the networking stack through the log crate. The events are emitted with the TRACE log level.

This feature is enabled by default.

Feature verbose

The verbose feature enables logging of events where the logging itself may incur very high overhead. For example, emitting a log line every time an application reads or writes as little as 1 octet from a socket is likely to overwhelm the application logic unless a BufReader or BufWriter is used, which are of course not available on heap-less systems.

This feature is disabled by default.

Hosted usage examples

smoltcp, being a freestanding networking stack, needs to be able to transmit and receive raw frames. For testing purposes, we will use a regular OS, and run smoltcp in a userspace process. Only Linux is supported (right now).

On *nix OSes, transmiting and receiving raw frames normally requires superuser privileges, but on Linux it is possible to create a persistent tap interface that can be manipulated by a specific user:

sudo ip tuntap add name tap0 mode tap user $USER
sudo ip link set tap0 up
sudo ip addr add 192.168.69.100/24 dev tap0

Fault injection

In order to demonstrate the response of smoltcp to adverse network conditions, all examples implement fault injection, available through command-line options:

  • The --drop-chance option randomly drops packets, with given probability in percents.
  • The --corrupt-chance option randomly mutates one octet in a packet, with given probability in percents.
  • The --size-limit option drops packets larger than specified size.
  • The --tx-rate-limit and --rx-rate-limit options set the amount of tokens for a token bucket rate limiter, in packets per bucket.
  • The --shaping-interval option sets the refill interval of a token bucket rate limiter, in milliseconds.

A good starting value for --drop-chance and --corrupt-chance is 15%. A good starting value for --?x-rate-limit is 4 and --shaping-interval is 50 ms.

Note that packets dropped by the fault injector still get traced; the rx: randomly dropping a packet message indicates that the packet above it got dropped, and the tx: randomly dropping a packet message indicates that the packet below it was.

examples/tcpdump.rs

examples/tcpdump.rs is a tiny clone of the tcpdump utility.

Unlike the rest of the examples, it uses raw sockets, and so it can be used on regular interfaces, e.g. eth0 or wlan0, as well as the tap0 interface we've created above.

Read its source code, then run it as:

cargo build --example tcpdump
sudo ./target/debug/tcpdump eth0

examples/server.rs

examples/server.rs emulates a network host that can respond to requests.

The host is assigned the hardware address 02-00-00-00-00-01 and IPv4 address 192.168.69.1.

Read its source code, then run it as:

cargo run --example server -- tap0

It responds to:

  • pings (ping 192.168.69.1);
  • UDP packets on port 6969 (socat stdio udp4-connect:192.168.69.1:6969 <<<"abcdefg"), where it will respond "yo dawg" to any incoming packet;
  • TCP packets on port 6969 (socat stdio tcp4-connect:192.168.69.1:6969), where it will respond "yo dawg" to any incoming connection and immediately close it;
  • TCP packets on port 6970 (socat stdio tcp4-connect:192.168.69.1:6970 <<<"abcdefg"), where it will respond with reversed chunks of the input indefinitely.
  • TCP packets on port 6971 (cat /dev/urandom | socat stdio tcp4-connect:192.168.69.1:6971), which will be ignored.

The buffers are only 64 bytes long, for convenience of testing resource exhaustion conditions.

examples/client.rs

examples/client.rs emulates a network host that can initiate requests.

The host is assigned the hardware address 02-00-00-00-00-02 and IPv4 address 192.168.69.2.

Read its source code, then run it as:

cargo run --example client -- tap0 ADDRESS PORT

It connects to the given address (not a hostname) and port (e.g. socat stdio tcp4-listen 1234), and will respond with reversed chunks of the input indefinitely.

examples/ping.rs

examples/ping.rs implements a minimal version of the ping utility using raw sockets.

The host is assigned the hardware address 02-00-00-00-00-02 and IPv4 address 192.168.69.1.

Read its source code, then run it as:

cargo run --example ping -- tap0 ADDRESS

It sends a series of 4 ICMP ECHO_REQUEST packets to the given address at one second intervals and prints out a status line on each valid ECHO_RESPONSE received.

The first ECHO_REQUEST packet is expected to be lost since arp_cache is empty after startup; the ECHO_REQUEST packet is dropped and an ARP request is sent instead.

Currently, netmasks are not implemented, and so the only address this example can reach is the other endpoint of the tap interface, 192.168.1.100. It cannot reach itself because packets entering a tap interface do not loop back.

Bare-metal usage examples

Examples that use no services from the host OS are necessarily less illustrative than examples that do. Because of this, only one such example is provided.

examples/loopback.rs

examples/loopback.rs performs a simple exchange between two TCP socket via a loopback interface. This example requires the collections feature to run.

Read its source code, then run it as:

cargo run --example loopback

If the std feature is enabled, it will print logs and packet dumps; otherwise, nothing at all will be displayed.

License

smoltcp is distributed under the terms of 0-clause BSD license.

See LICENSE-0BSD for details.