2017-08-21 14:38:36 +08:00
|
|
|
# smoltcp
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
_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.
|
|
|
|
|
2016-12-28 08:12:15 +08:00
|
|
|
_smoltcp_ does not need heap allocation *at all*, is [extensively documented][docs],
|
2017-09-21 05:52:28 +08:00
|
|
|
and compiles on stable Rust 1.20 and later.
|
2016-12-28 08:12:15 +08:00
|
|
|
|
2017-12-23 04:59:30 +08:00
|
|
|
_smoltcp_ achieves [~Gbps of throughput](#examplesbenchmarkrs) when tested against
|
|
|
|
the Linux TCP stack in loopback mode.
|
|
|
|
|
2016-12-28 08:21:01 +08:00
|
|
|
[docs]: https://docs.rs/smoltcp/
|
2016-12-28 08:12:15 +08:00
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
## Features
|
2016-12-10 17:23:40 +08:00
|
|
|
|
2017-09-25 00:07:24 +08:00
|
|
|
_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.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
### Media layer
|
|
|
|
|
|
|
|
The only supported medium is Ethernet.
|
|
|
|
|
2016-12-13 20:31:33 +08:00
|
|
|
* Regular Ethernet II frames are supported.
|
2017-03-06 12:01:06 +08:00
|
|
|
* Unicast and broadcast packets are supported, multicast packets are **not** supported.
|
2016-12-13 07:22:59 +08:00
|
|
|
* ARP packets (including gratuitous requests and replies) are supported.
|
2017-11-21 18:52:53 +08:00
|
|
|
* ARP requests are sent at a rate not exceeding one per second.
|
|
|
|
* Cached ARP entries expire after one minute.
|
2017-01-25 20:29:52 +08:00
|
|
|
* 802.3 frames and 802.1Q are **not** supported.
|
2016-12-13 04:01:38 +08:00
|
|
|
* Jumbo frames are **not** supported.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
### IP layer
|
|
|
|
|
2016-12-13 04:01:38 +08:00
|
|
|
The only supported internetworking protocol is IPv4.
|
|
|
|
|
2017-09-03 20:03:55 +08:00
|
|
|
* IPv4 header checksum is generated and validated.
|
2017-10-25 07:04:33 +08:00
|
|
|
* IPv4 time-to-live value is configurable per socket, set to 64 by default.
|
2017-10-25 08:30:57 +08:00
|
|
|
* IPv4 default gateway is supported.
|
2016-12-13 04:01:38 +08:00
|
|
|
* IPv4 fragmentation is **not** supported.
|
2017-09-03 20:03:55 +08:00
|
|
|
* IPv4 options are **not** supported and are silently ignored.
|
2017-10-25 08:30:57 +08:00
|
|
|
* IPv4 routes (other than the default one) are **not** supported.
|
2017-11-10 10:02:17 +08:00
|
|
|
|
|
|
|
### ICMP layer
|
|
|
|
|
|
|
|
The ICMPv4 protocol is supported, and ICMP sockets are available.
|
|
|
|
|
2016-12-15 01:39:44 +08:00
|
|
|
* ICMPv4 header checksum is supported.
|
2017-11-10 10:02:17 +08:00
|
|
|
* ICMPv4 echo replies are generated in response to echo requests.
|
|
|
|
* ICMP sockets can listen to ICMPv4 Port Unreachable messages, or any ICMPv4 messages with
|
|
|
|
a given IPv4 identifier field.
|
2017-09-03 20:03:55 +08:00
|
|
|
* ICMPv4 protocol unreachable messages are **not** passed to higher layers when received.
|
2017-11-10 10:02:17 +08:00
|
|
|
* ICMPv4 parameter problem messages are **not** generated.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
### UDP layer
|
|
|
|
|
2017-11-10 10:02:17 +08:00
|
|
|
The UDP protocol is supported over IPv4, and UDP sockets are available.
|
2016-12-15 01:39:44 +08:00
|
|
|
|
2017-09-18 19:05:40 +08:00
|
|
|
* Header checksum is always generated and validated.
|
2017-09-03 20:03:55 +08:00
|
|
|
* In response to a packet arriving at a port without a listening socket,
|
|
|
|
an ICMP destination unreachable message is generated.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
### TCP layer
|
|
|
|
|
2017-11-10 10:02:17 +08:00
|
|
|
The TCP protocol is supported over IPv4, and server and client TCP sockets are available.
|
2016-12-20 21:44:41 +08:00
|
|
|
|
2017-09-18 19:05:40 +08:00
|
|
|
* Header checksum is generated and validated.
|
2017-09-03 20:03:55 +08:00
|
|
|
* Maximum segment size is negotiated.
|
2017-09-18 19:05:40 +08:00
|
|
|
* Multiple packets are transmitted without waiting for an acknowledgement.
|
2017-09-23 03:37:49 +08:00
|
|
|
* Reassembly of out-of-order segments is supported, with no more than 4 gaps in sequence space.
|
|
|
|
* Keep-alive packets may be sent at a configurable interval.
|
|
|
|
* Retransmission timeout starts at a fixed interval of 100 ms and doubles every time.
|
|
|
|
* Time-wait timeout has a fixed interval of 10 s.
|
|
|
|
* User timeout has a configurable interval.
|
|
|
|
* Window scaling is **not** supported, and the maximum buffer size is 65536.
|
|
|
|
* Selective acknowledgements are **not** implemented.
|
2017-09-03 20:03:55 +08:00
|
|
|
* Delayed acknowledgements are **not** implemented.
|
2017-09-23 03:37:49 +08:00
|
|
|
* Silly window syndrome avoidance is **not** implemented.
|
2017-09-03 20:03:55 +08:00
|
|
|
* Nagle's algorithm is **not** implemented.
|
2017-09-23 03:37:49 +08:00
|
|
|
* Congestion control is **not** implemented.
|
|
|
|
* Timestamping is **not** supported.
|
|
|
|
* Urgent pointer is **ignored**.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
## Installation
|
2016-12-10 17:23:40 +08:00
|
|
|
|
|
|
|
To use the _smoltcp_ library in your project, add the following to `Cargo.toml`:
|
|
|
|
|
|
|
|
```toml
|
|
|
|
[dependencies]
|
2017-09-23 04:01:40 +08:00
|
|
|
smoltcp = "0.4"
|
2016-12-10 17:23:40 +08:00
|
|
|
```
|
|
|
|
|
2016-12-28 07:43:49 +08:00
|
|
|
The default configuration assumes a hosted environment, for ease of evaluation.
|
|
|
|
You probably want to disable default features and configure them one by one:
|
|
|
|
|
|
|
|
```toml
|
|
|
|
[dependencies]
|
2017-09-23 04:01:40 +08:00
|
|
|
smoltcp = { version = "0.4", default-features = false, features = ["log"] }
|
2016-12-28 07:43:49 +08:00
|
|
|
```
|
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
### Feature `std`
|
2016-12-28 07:43:49 +08:00
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
The `std` feature enables use of objects and slices owned by the networking stack through a
|
2017-06-15 18:12:11 +08:00
|
|
|
dependency on `std::boxed::Box` and `std::vec::Vec`.
|
2016-12-28 07:43:49 +08:00
|
|
|
|
2017-01-19 20:23:32 +08:00
|
|
|
This feature is enabled by default.
|
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
### Feature `alloc`
|
2016-12-28 07:49:37 +08:00
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
The `alloc` feature enables use of objects owned by the networking stack through a dependency
|
2017-09-23 03:54:47 +08:00
|
|
|
on collections from the `alloc` crate. This only works on nightly rustc.
|
2017-01-10 20:09:26 +08:00
|
|
|
|
2017-09-25 07:51:19 +08:00
|
|
|
This feature is disabled by default.
|
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
### Feature `log`
|
2016-12-28 07:43:49 +08:00
|
|
|
|
2017-03-05 13:49:38 +08:00
|
|
|
The `log` feature enables logging of events within the networking stack through
|
2017-08-01 19:21:58 +08:00
|
|
|
the [log crate][log]. 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.
|
2016-12-28 07:43:49 +08:00
|
|
|
|
|
|
|
[log]: https://crates.io/crates/log
|
|
|
|
|
2017-01-19 20:23:32 +08:00
|
|
|
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.
|
|
|
|
|
2017-09-25 07:51:19 +08:00
|
|
|
### Features `phy-raw_socket` and `phy-tap_interface`
|
|
|
|
|
|
|
|
Enable `smoltcp::phy::RawSocket` and `smoltcp::phy::TapInterface`, respectively.
|
|
|
|
|
|
|
|
These features are enabled by default.
|
|
|
|
|
2017-09-25 08:12:58 +08:00
|
|
|
### Features `socket-raw`, `socket-udp`, and `socket-tcp`
|
|
|
|
|
|
|
|
Enable `smoltcp::socket::RawSocket`, `smoltcp::socket::UdpSocket`,
|
|
|
|
and `smoltcp::socket::TcpSocket`, respectively.
|
|
|
|
|
|
|
|
These features are enabled by default.
|
|
|
|
|
2017-12-24 21:28:59 +08:00
|
|
|
### Features `proto-ipv4` and `proto-ipv6`
|
|
|
|
|
|
|
|
Enable [IPv4] and [IPv6] respectively.
|
|
|
|
|
|
|
|
[IPv4]: https://tools.ietf.org/rfc/rfc791.txt
|
|
|
|
[IPv6]: https://tools.ietf.org/rfc/rfc8200.txt
|
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
## Hosted usage examples
|
2016-12-10 17:23:40 +08:00
|
|
|
|
2016-12-13 20:31:33 +08:00
|
|
|
_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).
|
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
On \*nix OSes, transmiting and receiving raw frames normally requires superuser privileges, but
|
2016-12-13 20:31:33 +08:00
|
|
|
on Linux it is possible to create a _persistent tap interface_ that can be manipulated by
|
|
|
|
a specific user:
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
```sh
|
|
|
|
sudo ip tuntap add name tap0 mode tap user $USER
|
|
|
|
sudo ip link set tap0 up
|
2016-12-13 23:18:56 +08:00
|
|
|
sudo ip addr add 192.168.69.100/24 dev tap0
|
2016-12-10 17:23:40 +08:00
|
|
|
```
|
|
|
|
|
2017-10-03 15:28:00 +08:00
|
|
|
It's possible to let _smoltcp_ access Internet by enabling routing for the tap interface:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
sudo iptables -t nat -A POSTROUTING -s 192.168.69.0/24 -j MASQUERADE
|
|
|
|
sudo sysctl net.ipv4.ip_forward=1
|
|
|
|
```
|
|
|
|
|
2017-05-29 18:53:30 +08:00
|
|
|
### 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.
|
|
|
|
|
2017-06-26 16:26:42 +08:00
|
|
|
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.
|
|
|
|
|
2017-07-24 06:36:56 +08:00
|
|
|
### Packet dumps
|
|
|
|
|
|
|
|
All examples provide a `--pcap` option that writes a [libpcap] file containing a view of every
|
|
|
|
packet as it is seen by _smoltcp_.
|
|
|
|
|
|
|
|
[libpcap]: https://wiki.wireshark.org/Development/LibpcapFileFormat
|
|
|
|
|
2016-12-28 08:18:10 +08:00
|
|
|
### examples/tcpdump.rs
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2016-12-28 08:18:10 +08:00
|
|
|
_examples/tcpdump.rs_ is a tiny clone of the _tcpdump_ utility.
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2016-12-28 08:18:10 +08:00
|
|
|
Read its [source code](/examples/tcpdump.rs), then run it as:
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
```sh
|
2016-12-28 08:18:10 +08:00
|
|
|
cargo build --example tcpdump
|
|
|
|
sudo ./target/debug/tcpdump eth0
|
2016-12-12 15:19:53 +08:00
|
|
|
```
|
|
|
|
|
2017-12-18 22:53:09 +08:00
|
|
|
### examples/httpclient.rs
|
|
|
|
|
|
|
|
_examples/httpclient.rs_ emulates a network host that can initiate HTTP requests.
|
|
|
|
|
|
|
|
The host is assigned the hardware address `02-00-00-00-00-02` and IPv4 address `192.168.69.1`.
|
|
|
|
|
|
|
|
Read its [source code](/examples/httpclient.rs), then run it as:
|
|
|
|
|
|
|
|
```sh
|
2017-12-22 21:13:43 +08:00
|
|
|
cargo run --example httpclient -- tap0 ADDRESS URL
|
2017-12-18 22:53:09 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
```sh
|
2017-12-22 21:13:43 +08:00
|
|
|
cargo run --example httpclient -- tap0 93.184.216.34 http://example.org/
|
2017-12-18 22:53:09 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
It connects to the given address (not a hostname) and URL, and prints any returned response data.
|
|
|
|
The TCP socket buffers are limited to 1024 bytes to make packet traces more interesting.
|
|
|
|
|
|
|
|
### 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](/examples/ping.rs), then run it as:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
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.
|
|
|
|
|
2016-12-28 08:18:10 +08:00
|
|
|
### examples/server.rs
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2017-12-18 22:53:09 +08:00
|
|
|
_examples/server.rs_ emulates a network host that can respond to basic requests.
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
The host is assigned the hardware address `02-00-00-00-00-01` and IPv4 address `192.168.69.1`.
|
|
|
|
|
2016-12-28 08:18:10 +08:00
|
|
|
Read its [source code](/examples/server.rs), then run it as:
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
```sh
|
2016-12-28 08:18:10 +08:00
|
|
|
cargo run --example server -- tap0
|
2016-12-12 15:19:53 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
It responds to:
|
|
|
|
|
2016-12-28 02:04:02 +08:00
|
|
|
* pings (`ping 192.168.69.1`);
|
2016-12-26 22:50:12 +08:00
|
|
|
* UDP packets on port 6969 (`socat stdio udp4-connect:192.168.69.1:6969 <<<"abcdefg"`),
|
2017-07-30 14:59:01 +08:00
|
|
|
where it will respond "hello" to any incoming packet;
|
2017-08-31 17:09:13 +08:00
|
|
|
* TCP connections on port 6969 (`socat stdio tcp4-connect:192.168.69.1:6969`),
|
2017-07-30 14:59:01 +08:00
|
|
|
where it will respond "hello" to any incoming connection and immediately close it;
|
2017-08-31 17:09:13 +08:00
|
|
|
* TCP connections on port 6970 (`socat stdio tcp4-connect:192.168.69.1:6970 <<<"abcdefg"`),
|
2016-12-28 02:04:02 +08:00
|
|
|
where it will respond with reversed chunks of the input indefinitely.
|
2017-08-31 17:09:13 +08:00
|
|
|
* TCP connections on port 6971 (`socat stdio tcp4-connect:192.168.69.1:6971 </dev/urandom`),
|
2017-09-24 21:58:53 +08:00
|
|
|
which will sink data. Also, keep-alive packets (every 1 s) and a user timeout (at 2 s)
|
|
|
|
are enabled on this port; try to trigger them using fault injection.
|
2017-08-31 17:09:13 +08:00
|
|
|
* TCP connections on port 6972 (`socat stdio tcp4-connect:192.168.69.1:6972 >/dev/null`),
|
|
|
|
which will source data.
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2017-07-30 09:17:48 +08:00
|
|
|
Except for the socket on port 6971. the buffers are only 64 bytes long, for convenience
|
|
|
|
of testing resource exhaustion conditions.
|
2016-12-27 00:29:33 +08:00
|
|
|
|
2017-03-05 14:15:15 +08:00
|
|
|
### examples/client.rs
|
|
|
|
|
2017-12-18 22:53:09 +08:00
|
|
|
_examples/client.rs_ emulates a network host that can initiate basic requests.
|
2017-03-05 14:15:15 +08:00
|
|
|
|
|
|
|
The host is assigned the hardware address `02-00-00-00-00-02` and IPv4 address `192.168.69.2`.
|
|
|
|
|
|
|
|
Read its [source code](/examples/client.rs), then run it as:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
cargo run --example client -- tap0 ADDRESS PORT
|
|
|
|
```
|
|
|
|
|
2017-08-25 14:20:10 +08:00
|
|
|
It connects to the given address (not a hostname) and port (e.g. `socat stdio tcp4-listen:1234`),
|
2017-03-05 14:15:15 +08:00
|
|
|
and will respond with reversed chunks of the input indefinitely.
|
|
|
|
|
2017-12-23 04:59:30 +08:00
|
|
|
### examples/benchmark.rs
|
|
|
|
|
|
|
|
_examples/benchmark.rs_ implements a simple throughput benchmark.
|
|
|
|
|
|
|
|
Read its [source code](/examples/benchmark.rs), then run it as:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
cargo run --release --example benchmark -- tap0 [reader|writer]
|
|
|
|
```
|
|
|
|
|
|
|
|
It establishes a connection to itself from a different thread and reads or writes a large amount
|
|
|
|
of data in one direction.
|
|
|
|
|
|
|
|
A typical result (achieved on a Intel Core i7-7500U CPU and a Linux 4.9.65 x86_64 kernel running
|
|
|
|
on a Dell XPS 13 9360 laptop) is as follows:
|
|
|
|
|
|
|
|
```
|
|
|
|
$ cargo run -q --release --example benchmark tap0 reader
|
2017-12-23 20:17:17 +08:00
|
|
|
throughput: 2.556 Gbps
|
2017-12-23 04:59:30 +08:00
|
|
|
$ cargo run -q --release --example benchmark tap0 writer
|
2017-12-23 20:17:17 +08:00
|
|
|
throughput: 5.301 Gbps
|
2017-12-23 04:59:30 +08:00
|
|
|
```
|
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
## Bare-metal usage examples
|
2017-07-14 11:17:55 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2017-07-24 06:36:56 +08:00
|
|
|
_examples/loopback.rs_ sets up _smoltcp_ to talk with itself via a loopback interface.
|
2017-12-22 16:54:58 +08:00
|
|
|
Although it does not require `std`, this example still requires the `alloc` feature to run.
|
2017-07-14 11:17:55 +08:00
|
|
|
|
2017-07-24 06:36:56 +08:00
|
|
|
Read its [source code](/examples/loopback.rs), then run it without `std`:
|
2017-07-14 11:17:55 +08:00
|
|
|
|
|
|
|
```sh
|
2017-12-22 16:54:58 +08:00
|
|
|
cargo run --example loopback --no-default-features --features alloc
|
2017-07-14 11:17:55 +08:00
|
|
|
```
|
|
|
|
|
2017-07-24 06:36:56 +08:00
|
|
|
... or with `std`:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
cargo run --example loopback -- --pcap loopback.pcap
|
|
|
|
```
|
|
|
|
|
|
|
|
It opens a server and a client TCP socket, and transfers a chunk of data. You can examine
|
|
|
|
the packet exchange by opening `loopback.pcap` in [Wireshark].
|
|
|
|
|
|
|
|
If the `std` feature is enabled, it will print logs and packet dumps, and fault injection
|
|
|
|
is possible; otherwise, nothing at all will be displayed and no options are accepted.
|
|
|
|
|
|
|
|
[wireshark]: https://wireshark.org
|
2017-07-14 11:17:55 +08:00
|
|
|
|
2017-08-21 14:38:36 +08:00
|
|
|
## License
|
2016-12-10 17:23:40 +08:00
|
|
|
|
2016-12-28 08:27:49 +08:00
|
|
|
_smoltcp_ is distributed under the terms of 0-clause BSD license.
|
2016-12-10 17:23:40 +08:00
|
|
|
|
2016-12-28 08:27:49 +08:00
|
|
|
See [LICENSE-0BSD](LICENSE-0BSD.txt) for details.
|