a smol tcp/ip stack
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.91 and later.
smoltcp achieves ~Gbps of throughput when tested against the Linux TCP stack in loopback mode.
smoltcp is missing many widely deployed features, usually because no one implemented them yet. To set expectations right, both implemented and omitted features are listed.
There are 3 supported mediums.
The IGMPv1 and IGMPv2 protocols are supported, and IPv4 multicast is available.
The ICMPv4 protocol is supported, and ICMP sockets are available.
The ICMPv6 protocol is supported, and ICMP sockets are available.
The UDP protocol is supported over IPv4 and IPv6, and UDP sockets are available.
The TCP protocol is supported over IPv4 and IPv6, and server and client TCP sockets are available.
CUBIC and Reno are implemented.To use the smoltcp library in your project, add the following to Cargo.toml:
[dependencies]
smoltcp = "0.10.0"
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.10.0", default-features = false, features = ["log"] }
stdThe 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.
allocThe alloc feature enables use of objects owned by the networking stack through a dependency
on collections from the alloc crate. This only works on nightly rustc.
This feature is disabled by default.
logThe log feature enables logging of events within the networking stack through
the log crate. Normal events (e.g. buffer level or TCP state changes) are emitted with
the TRACE log level. Exceptional events (e.g. malformed packets) are emitted with
the DEBUG log level.
This feature is enabled by default.
defmtThe defmt feature enables logging of events with the defmt crate.
This feature is disabled by default, and cannot be used at the same time as log.
verboseThe 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.
phy-raw_socket and phy-tuntap_interfaceEnable smoltcp::phy::RawSocket and smoltcp::phy::TunTapInterface, respectively.
These features are enabled by default.
socket-raw, socket-udp, socket-tcp, socket-icmp, socket-dhcpv4, socket-dnsEnable the corresponding socket type.
These features are enabled by default.
proto-ipv4, proto-ipv6 and proto-sixlowpanEnable IPv4, IPv6 and 6LoWPAN respectively.
smoltcp has some configuration settings that are set at compile time, affecting sizes and counts of buffers.
They can be set in two ways:
<name>-<value>. name must be in lowercase and
use dashes instead of underscores. For example. iface-max-addr-count-3. Only a selection of values
is available, check Cargo.toml for the list.SMOLTCP_<value>. For example
SMOLTCP_IFACE_MAX_ADDR_COUNT=3 cargo build. You can also set them in the [env] section of .cargo/config.toml.
Any value can be set, unlike with Cargo features.Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting with different values, compilation fails.
IFACE_MAX_ADDR_COUNTMax amount of IP addresses that can be assigned to one interface (counting both IPv4 and IPv6 addresses). Default: 2.
IFACE_MAX_MULTICAST_GROUP_COUNTMax amount of multicast groups that can be joined by one interface. Default: 4.
IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNTMax amount of 6LoWPAN address contexts that can be assigned to one interface. Default: 4.
IFACE_NEIGHBOR_CACHE_COUNTAmount of "IP address -> hardware address" entries the neighbor cache (also known as the "ARP cache" or the "ARP table") holds. Default: 4.
IFACE_MAX_ROUTE_COUNTMax amount of routes that can be added to one interface. Includes the default route. Includes both IPv4 and IPv6. Default: 2.
IFACE_MAX_PREFIX_COUNTMax amount of IPv6 prefixes that can be added to one interface via SLAAC.
Should be lower or equal to IFACE_MAX_ADDR_COUNT.
FRAGMENTATION_BUFFER_SIZESize of the buffer used for fragmenting outgoing packets larger than the MTU. Packets larger than this setting will be dropped instead of fragmented. Default: 1500.
ASSEMBLER_MAX_SEGMENT_COUNTMaximum number of non-contiguous segments the assembler can hold. Used for both packet reassembly and TCP stream reassembly. Default: 4.
REASSEMBLY_BUFFER_SIZESize of the buffer used for reassembling (de-fragmenting) incoming packets. If the reassembled packet is larger than this setting, it will be dropped instead of reassembled. Default: 1500.
REASSEMBLY_BUFFER_COUNTNumber of reassembly buffers, i.e how many different incoming packets can be reassembled at the same time. Default: 1.
DNS_MAX_RESULT_COUNTMaximum amount of address results for a given DNS query that will be kept. For example, if this is set to 2 and the queried name has 4 A records, only the first 2 will be returned. Default: 1.
DNS_MAX_SERVER_COUNTMaximum amount of DNS servers that can be configured in one DNS socket. Default: 1.
DNS_MAX_NAME_SIZEMaximum length of DNS names that can be queried. Default: 255.
The maximum amount of parsed options the IPv6 Hop-by-Hop header can hold. Default: 4.
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, transmitting 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
sudo ip -6 addr add fe80::100/64 dev tap0
sudo ip -6 addr add fdaa::100/64 dev tap0
sudo ip -6 route add fe80::/64 dev tap0
sudo ip -6 route add fdaa::/64 dev tap0
It's possible to let smoltcp access Internet by enabling routing for the tap interface:
sudo iptables -t nat -A POSTROUTING -s 192.168.69.0/24 -j MASQUERADE
sudo sysctl net.ipv4.ip_forward=1
sudo ip6tables -t nat -A POSTROUTING -s fdaa::/64 -j MASQUERADE
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Some distros have a default policy o
No open issues yet, or sync has not completed.