The smoltcp library is built in a layered structure, with the layers corresponding to the levels of API abstraction. Only the highest layers would be used by a typical application; however, the goal of smoltcp is not just to provide a simple interface for writing applications but also to be a toolbox of networking primitives, so every layer is fully exposed and documented.
When discussing networking stacks and layering, often the OSI model is invoked. smoltcp makes no effort to conform to the OSI model as it is not applicable to TCP/IP.
The socket layer APIs are provided in the module socket; currently, raw, ICMP, TCP, and UDP sockets are provided. The socket API provides the usual primitives, but necessarily differs in many from the Berkeley socket API, as the latter was not designed to be used without heap allocation.
The socket layer provides the buffering, packet construction and validation, and (for stateful sockets) the state machines, but it is interface-agnostic. An application must use sockets together with a network interface.
The interface layer APIs are provided in the module iface; currently, Ethernet interface is provided.
The interface layer handles the control messages, physical addressing and neighbor discovery. It routes packets to and from sockets.
The physical layer APIs are provided in the module phy; currently, raw socket and TAP interface are provided. In addition, two middleware interfaces are provided: the tracer device, which prints a human-readable representation of packets, and the fault injector device, which randomly introduces errors into the transmitted and received packet sequences.
The physical layer handles interaction with a platform-specific network device.
Unlike the higher layers, the wire layer APIs will not be used by a typical application. They however are the bedrock of smoltcp, and everything else is built on top of them.
The wire layer APIs are designed by the principle “make illegal states ir-representable”. If a wire layer object can be constructed, then it can also be parsed from or emitted to a lower level.
The wire layer APIs also provide tcpdump-like pretty printing.
The representation layer APIs are provided in the module wire.
The representation layer exists to reduce the state space of raw packets. Raw packets may be nonsensical in a multitude of ways: invalid checksums, impossible combinations of flags, pointers to fields out of bounds, meaningless options… Representations shed all that, as well as any features not supported by smoltcp.
The packet layer APIs are also provided in the module wire.
The packet layer exists to provide a more structured way to work with packets than treating them as sequences of octets. It makes no judgement as to content of the packets, except where necessary to provide safe access to fields, and strives to implement every feature ever defined, to ensure that, when the representation layer is unable to make sense of a packet, it is still logged correctly and in full.
This crate is guaranteed to compile on stable Rust 1.65 and up with any valid set of features. It might compile on older versions but that may change in any new patch release.
The exception is when using the
defmt feature, in which case
defmt’s MSRV applies, which
- Network interface logic.
- Access to networking hardware.
- Communication between endpoints.
- Specialized containers.
- Time structures.
- Low-level packet access and construction.