### Create smoltcp Interface Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/README.md This example demonstrates the minimal setup required to create a smoltcp network interface using the loopback device. It configures a hardware address and initializes the interface. ```rust #[cfg(not(any(test, feature = "std")))] fn main() {} #[cfg(any(test, feature = "std"))] fn main() { use smoltcp::iface::{Interface, Config}; use smoltcp::phy::Loopback; use smoltcp::wire::HardwareAddress; use smoltcp::time::Instant; let hardware_addr = HardwareAddress::Ethernet([0x02, 0x00, 0x00, 0x00, 0x00, 0x01].into()); let config = Config::new(hardware_addr); let mut device = Loopback::new(Default::default()); let mut iface = Interface::new(config, &mut device, Instant::ZERO); println!("Interface created: {:?}", iface.hardware_addr()); } ``` -------------------------------- ### Basic Network Interface Setup in Rust Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/README.md Sets up a network interface using smoltcp, configures an IP address, and initializes TCP sockets. This is a foundational example for network communication. ```rust use smoltcp::iface::{Interface, Config, SocketSet}; use smoltcp::phy::{Device, TunTapInterface, Medium}; use smoltcp::socket::tcp; use smoltcp::storage::RingBuffer; use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpCidr, Ipv4Address}; // Create interface let hardware_addr = HardwareAddress::Ethernet([0x02, 0x00, 0x00, 0x00, 0x00, 0x01].into()); let config = Config::new(hardware_addr); let mut device = TunTapInterface::new("tap0", Medium::Ethernet)?; let mut iface = Interface::new(config, &mut device, Instant::ZERO); // Configure IP address iface.update_ip_addrs(|addrs| { addrs.push(IpCidr::new(Ipv4Address::new(192, 168, 1, 1).into(), 24)).ok(); }); // Create sockets let mut rx_buf = [0u8; 2048]; let mut tx_buf = [0u8; 2048]; let tcp_socket = tcp::Socket::new( RingBuffer::new(&mut rx_buf[..]), RingBuffer::new(&mut tx_buf[..]) ); let tcp_handle = sockets.add(tcp_socket.upcast()); // Main loop loop { let now = Instant::now(); iface.poll(now, &mut device, &mut sockets); // Work with sockets let socket = tcp::Socket::downcast_mut(&mut sockets.get_mut(tcp_handle)).unwrap(); if socket.may_send() { socket.send_slice(b"Hello")?; } } ``` -------------------------------- ### Simple HTTP Server Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/tcp-socket.md An example demonstrating how to set up a simple HTTP server using smoltcp's TCP sockets. ```APIDOC ## Example: Simple HTTP Server ```rust use smoltcp::socket::{Socket, AnySocket}; use smoltcp::socket::tcp::{Socket as TcpSocket, State}; let mut rx_buf = [0u8; 2048]; let mut tx_buf = [0u8; 2048]; let rx_buffer = smoltcp::storage::RingBuffer::new(&mut rx_buf[..]); let tx_buffer = smoltcp::storage::RingBuffer::new(&mut tx_buf[..]); let mut socket = TcpSocket::new(rx_buffer, tx_buffer); socket.listen(("0.0.0.0", 80))?; let mut socket_set = smoltcp::iface::SocketSet::new(vec![socket.upcast()]); loop { iface.poll(now, &mut device, &mut socket_set); let mut socket = TcpSocket::downcast_mut(&mut socket_set.get_mut(handle)).unwrap(); if socket.may_recv() { let mut data = [0u8; 512]; if let Ok(n) = socket.recv_slice(&mut data) { // Process request socket.send_slice(b"HTTP/1.1 200 OK\r\n\r\nHello")?; } } } ``` ``` -------------------------------- ### Run loopback benchmark example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Execute the loopback benchmark example in release mode to measure throughput performance over a loopback interface. This example relies on 'std' for timing. ```sh cargo run --release --example loopback_benchmark ``` -------------------------------- ### Build and Run Tcpdump Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Builds the tcpdump example and runs it with superuser privileges on a specified network interface. ```sh cargo build --example tcpdump sudo ./target/debug/examples/tcpdump eth0 ``` -------------------------------- ### Run Httpclient Example (IPv6) Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Executes the httpclient example to make an HTTP request to a given IPv6 address and URL. Requires the tap interface to be set up. ```sh cargo run --example httpclient -- --tap tap0 2606:2800:220:1:248:1893:25c8:1946 http://example.org/ ``` -------------------------------- ### Run Httpclient Example (IPv4) Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Executes the httpclient example to make an HTTP request to a given IPv4 address and URL. Requires the tap interface to be set up. ```sh cargo run --example httpclient -- --tap tap0 93.184.216.34 http://example.org/ ``` -------------------------------- ### Run loopback example with std Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Execute the loopback example with the 'std' feature enabled, which simplifies feature listing and allows for PCAP output for network analysis. ```sh cargo run --example loopback -- --pcap loopback.pcap ``` -------------------------------- ### DHCP Configuration Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md An example demonstrating how to use the DHCPv4 socket to obtain and apply network configuration. ```APIDOC ## Example: DHCP Configuration ### Description This example shows how to initialize a DHCPv4 socket, poll for network interface events, and apply the obtained configuration (IP address, router) to the interface. ### Code ```rust use smoltcp::socket::dhcpv4::* use smoltcp::socket::Socket; let socket = Socket::new(); let handle = sockets.add(socket.upcast()); loop { iface.poll(now, &mut device, &mut sockets); let socket = dhcpv4::Socket::downcast(sockets.get(handle)).unwrap(); match socket.state() { ClientState::Bound => { if let Some(config) = socket.config() { println!("Got DHCP lease: {}", config.address); // Apply configuration to interface iface.update_ip_addrs(|addrs| { addrs.push(config.address.into()).ok(); }); if let Some(router) = config.router { iface.routes().add_default_ipv4_route(router).ok(); } } break; } ClientState::Idle => { println!("DHCP failed, retrying..."); socket.reset(); } _ => { println!("DHCP state: {:?}", socket.state()); } } } ``` ``` -------------------------------- ### RawSocket Constructor Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Example of creating a RawSocket for Linux. This requires the 'phy-raw_socket' feature to be enabled. ```rust use smoltcp::phy::{RawSocket, Medium}; let device = RawSocket::new("eth0", Medium::Ethernet)?; ``` -------------------------------- ### Ping Implementation Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/raw-icmp-socket.md An example demonstrating how to implement a basic ping utility using the raw ICMP socket. It covers setting up buffers, binding to an endpoint, sending ping requests, and receiving pong replies. ```APIDOC ## Example: Ping Implementation ```rust use smoltcp::socket::icmp::*; use smoltcp::storage::PacketMetadata; use smoltcp::wire::IpAddress; let mut rx_packets = [PacketMetadata::EMPTY; 2]; let mut rx_data = [0u8; 256]; let rx_buffer = PacketBuffer::new(&mut rx_packets[..], &mut rx_data[..]); let mut tx_packets = [PacketMetadata::EMPTY; 2]; let mut tx_data = [0u8; 256]; let tx_buffer = PacketBuffer::new(&mut tx_packets[..], &mut tx_data[..]); let mut socket = Socket::new(rx_buffer, tx_buffer); socket.bind(Endpoint::Ident(0x1234))?; // Send ping socket.send_slice(b"Hello", "8.8.8.8".parse().unwrap())?; loop { iface.poll(now, &mut device, &mut sockets); if socket.may_recv() { let mut buf = [0u8; 32]; match socket.recv_slice(&mut buf) { Ok((n, src)) => { println!("Pong from {}: {} bytes", src, n); } Err(e) => eprintln!("Error: {}", e), } } } ``` ``` -------------------------------- ### Run loopback example without std Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Execute the loopback example without the 'std' feature, requiring explicit feature flags for logging, IPv4, TCP sockets, and allocation. ```sh cargo run --example loopback --no-default-features --features="log proto-ipv4 socket-tcp alloc" ``` -------------------------------- ### Receive Frame Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Example of how to receive a frame using the `receive` method. It checks if a frame is available and processes its data if received. ```rust if let Some((rx_token, tx_token)) = device.receive(now) { let data = rx_token.consume(|data| { println!("Received {} bytes", data.len()); data.len() }); } ``` -------------------------------- ### DHCPv4 Configuration Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md Demonstrates how to use the DHCPv4 socket to obtain network configuration. This example polls the interface for DHCP state, applies the obtained configuration (IP address and router), and breaks the loop once a lease is bound. It includes error handling for DHCP failures. ```rust use smoltcp::socket::dhcpv4::*; use smoltcp::socket::Socket; let socket = Socket::new(); let handle = sockets.add(socket.upcast()); loop { iface.poll(now, &mut device, &mut sockets); let socket = dhcpv4::Socket::downcast(sockets.get(handle)).unwrap(); match socket.state() { ClientState::Bound => { if let Some(config) = socket.config() { println!("Got DHCP lease: {}", config.address); // Apply configuration to interface iface.update_ip_addrs(|addrs| { addrs.push(config.address.into()).ok(); }); if let Some(router) = config.router { iface.routes().add_default_ipv4_route(router).ok(); } } break; } ClientState::Idle => { println!("DHCP failed, retrying..."); socket.reset(); } _ => { println!("DHCP state: {:?}", socket.state()); } } } ``` -------------------------------- ### TunTapInterface Constructor Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Example of creating a TunTapInterface for Linux. This requires the 'phy-tuntap_interface' feature to be enabled. ```rust use smoltcp::phy::{TunTapInterface, Medium}; let device = TunTapInterface::new("tap0", Medium::Ethernet)?; ``` -------------------------------- ### DeviceCapabilities Struct Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md An example instantiation of the DeviceCapabilities struct. This shows typical values for a device with a 1500 MTU, single burst reception, Ethernet medium, and default checksum capabilities. ```rust pub struct DeviceCapabilities { max_transmission_unit: 1500, max_burst_size: Some(1), medium: Medium::Ethernet, checksum: ChecksumCapabilities::default(), } ``` -------------------------------- ### UDP DNS Client Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/udp-socket.md Demonstrates how to set up a UDP socket to send DNS queries and process responses. Requires an active network interface and sockets. ```rust use smoltcp::socket::udp::*; use smoltcp::storage::PacketMetadata; let mut rx_packets = [PacketMetadata::EMPTY; 4]; let mut rx_data = [0u8; 4096]; let rx_buffer = PacketBuffer::new(&mut rx_packets[..], &mut rx_data[..]); let mut tx_packets = [PacketMetadata::EMPTY; 4]; let mut tx_data = [0u8; 1024]; let tx_buffer = PacketBuffer::new(&mut tx_packets[..], &mut tx_data[..]); let mut socket = Socket::new(rx_buffer, tx_buffer); socket.bind(("192.168.1.1", 5353))?; // Send DNS query let query = b"...dns packet data..."; socket.send_slice(query, ("8.8.8.8", 53))?; loop { iface.poll(now, &mut device, &mut sockets); let mut buf = [0u8; 512]; match socket.recv_slice(&mut buf) { Ok((n, src)) => { println!("DNS response from {}: {} bytes", src, n); // Process response } Err(RecvError::Exhausted) => { // No response yet } _ => {} } } ``` -------------------------------- ### IpEndpoint Construction Examples Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/types.md Shows how to construct an IpEndpoint using the From trait. Demonstrates creating endpoints from string addresses and Ipv4Address tuples. ```rust let ep1: IpEndpoint = ("192.168.1.1", 8080).into(); let ep2: IpEndpoint = (Ipv4Address::new(192, 168, 1, 1), 8080).into(); ``` -------------------------------- ### Simple HTTP Server Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/tcp-socket.md Demonstrates setting up a simple HTTP server using smoltcp's TCP sockets. It involves creating buffers, initializing a TCP socket, listening on a port, and handling incoming requests and responses. ```rust use smoltcp::socket::{Socket, AnySocket}; use smoltcp::socket::tcp::{Socket as TcpSocket, State}; let mut rx_buf = [0u8; 2048]; let mut tx_buf = [0u8; 2048]; let rx_buffer = smoltcp::storage::RingBuffer::new(&mut rx_buf[..]); let tx_buffer = smoltcp::storage::RingBuffer::new(&mut tx_buf[..]); let mut socket = TcpSocket::new(rx_buffer, tx_buffer); socket.listen(("0.0.0.0", 80))?; let mut socket_set = smoltcp::iface::SocketSet::new(vec![socket.upcast()]); loop { iface.poll(now, &mut device, &mut socket_set); let mut socket = TcpSocket::downcast_mut(&mut socket_set.get_mut(handle)).unwrap(); if socket.may_recv() { let mut data = [0u8; 512]; if let Ok(n) = socket.recv_slice(&mut data) { // Process request socket.send_slice(b"HTTP/1.1 200 OK\r\n\r\nHello")?; } } } ``` -------------------------------- ### Instant Arithmetic Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/types.md Demonstrates arithmetic operations on `Instant` and `Duration` for time calculations. ```rust let later = now + Duration::from_secs(5); let diff = later - now; ``` -------------------------------- ### Handling StartQueryError in Rust Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/errors.md Example of matching on `StartQueryError` to provide specific feedback or retry logic for DNS query failures. ```rust match socket.start_query("example.com", Type::A, MulticastDns::Disabled) { Ok(handle) => println!("Query started"), Err(StartQueryError::NoFreeSlot) => { eprintln!("Too many queries, wait for one to complete"); // Wait for a query result then retry } Err(StartQueryError::InvalidName) => eprintln!("Invalid hostname"), Err(StartQueryError::NameTooLong) => eprintln!("Hostname too long"), } ``` -------------------------------- ### HardwareAddress Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/types.md Demonstrates creating a HardwareAddress of the Ethernet variant with a specific MAC address. Used for link-layer addressing. ```rust let mac = HardwareAddress::Ethernet([0x02, 0x00, 0x00, 0x00, 0x00, 0x01].into()); ``` -------------------------------- ### Loopback benchmark performance output Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md Example output from the loopback benchmark, indicating the time taken and the achieved bandwidth. ```text $ cargo run --release --example loopback_benchmark done in 0.558 s, bandwidth is 15.395083 Gbps ``` -------------------------------- ### IpListenEndpoint Examples Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/types.md Illustrates creating an IpListenEndpoint for listening on all interfaces or a specific address. Useful for server socket configurations. ```rust // Listen on all interfaces port 8080 let ep = IpListenEndpoint { addr: None, port: 8080, }; // Listen on specific address let ep = IpListenEndpoint { addr: Some(Ipv4Address::new(192, 168, 1, 1).into()), port: 8080, }; ``` -------------------------------- ### DNS Socket Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md Demonstrates how to perform a DNS query for an A record, set DNS servers, and handle the query result. It includes polling the interface and checking the query status until resolution is complete or fails. ```rust use smoltcp::socket::dns::* use smoltcp::wire::dns::Type; let mut query_storage = [None; 1]; let mut socket = Socket::new(&mut query_storage[..]); socket.set_servers(&["8.8.8.8".parse().unwrap()])?; let handle = socket.start_query("example.com", Type::A, MulticastDns::Disabled)?; loop { iface.poll(now, &mut device, &mut sockets); match socket.get_query_result(handle) { Ok(addrs) => { println!("Resolved addresses:"); for addr in addrs { println!(" {}", addr); } break; } Err(GetQueryResultError::Pending) => { // Still waiting, continue polling } Err(GetQueryResultError::Failed) => { eprintln!("DNS resolution failed"); break; } } } ``` -------------------------------- ### start_query Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md Starts a DNS query for a given hostname. This method initiates a DNS lookup and returns a handle to track the query's progress. ```APIDOC ## start_query ### Description Starts a DNS query for the given hostname. ### Method Signature ```rust pub fn start_query( &mut self, name: &str, query_type: Type, mdns: MulticastDns ) -> Result ``` ### Parameters #### Path Parameters - **name** (`&str`) - Required - Hostname to resolve (e.g., "example.com") - **query_type** (`Type`) - Required - Query type (A for IPv4, AAAA for IPv6, etc.) - **mdns** (`MulticastDns`) - Required - Use mDNS or standard DNS ### Returns - `Result` - Handle to the query ### Errors - `StartQueryError::NoFreeSlot` - All query slots in use - `StartQueryError::InvalidName` - Hostname format invalid - `StartQueryError::NameTooLong` - Name exceeds `DNS_MAX_NAME_SIZE` ### Example ```rust use smoltcp::wire::dns::Type; let handle = socket.start_query("example.com", Type::A, MulticastDns::Disabled)?; ``` ``` -------------------------------- ### Ping Implementation Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/raw-icmp-socket.md Demonstrates how to set up and use an ICMP socket to send ping requests and receive echo replies. It includes buffer initialization, socket binding, sending a ping slice, and a loop for receiving responses. ```rust use smoltcp::socket::icmp::*; use smoltcp::storage::PacketMetadata; use smoltcp::wire::IpAddress; let mut rx_packets = [PacketMetadata::EMPTY; 2]; let mut rx_data = [0u8; 256]; let rx_buffer = PacketBuffer::new(&mut rx_packets[..], &mut rx_data[..]); let mut tx_packets = [PacketMetadata::EMPTY; 2]; let mut tx_data = [0u8; 256]; let tx_buffer = PacketBuffer::new(&mut tx_packets[..], &mut tx_data[..]); let mut socket = Socket::new(rx_buffer, tx_buffer); socket.bind(Endpoint::Ident(0x1234))?; // Send ping socket.send_slice(b"Hello", "8.8.8.8".parse().unwrap())?; loop { iface.poll(now, &mut device, &mut sockets); if socket.may_recv() { let mut buf = [0u8; 32]; match socket.recv_slice(&mut buf) { Ok((n, src)) => { println!("Pong from {}: {} bytes", src, n); } Err(e) => eprintln!("Error: {}", e), } } } ``` -------------------------------- ### UDP Echo Server Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/udp-socket.md Illustrates creating a simple UDP echo server that binds to a port and echoes received data back to the sender. Requires an active network interface and sockets. ```rust use smoltcp::socket::udp::*; use smoltcp::storage::PacketMetadata; let mut rx_packets = [PacketMetadata::EMPTY; 4]; let mut rx_data = [0u8; 4096]; let rx_buffer = PacketBuffer::new(&mut rx_packets[..], &mut rx_data[..]); let mut tx_packets = [PacketMetadata::EMPTY; 4]; let mut tx_data = [0u8; 4096]; let tx_buffer = PacketBuffer::new(&mut tx_packets[..], &mut tx_data[..]); let mut socket = Socket::new(rx_buffer, tx_buffer); socket.bind(("0.0.0.0", 6969))?; loop { iface.poll(now, &mut device, &mut sockets); let mut buf = [0u8; 512]; while socket.may_recv() { match socket.recv_slice(&mut buf) { Ok((n, src)) => { // Echo back to sender socket.send_slice(&buf[..n], src)?; } Err(_) => break, } } } ``` -------------------------------- ### Ipv4Cidr Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/types.md Demonstrates creating an Ipv4Cidr for the 192.168.1.0/24 network. This is useful for defining network subnets. ```rust // 192.168.1.0/24 let cidr = Ipv4Cidr::new( Ipv4Address::new(192, 168, 1, 1), 24 ); ``` -------------------------------- ### Emulate Network Client for Basic Requests Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md This example emulates a network client that initiates basic requests. It connects to a specified address and port, then responds with reversed chunks of input indefinitely. ```rust use std::env; use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes}; use smoltcp::phy::{Device, TapInterface}; use smoltcp::socket::{SocketSet, TCPv4, Socket, TCPv4Endpoint}; use smoltcp::time::{Duration, Instant}; use smoltcp::wire::{self, IpAddress, IpCidr, Ipv4Address}; const MTU: usize = 1500; struct ClientConfig { tap_device: String, address: IpAddress, port: u16, } impl ClientConfig { fn from_env() -> Result { let mut args = env::args().skip(1); let tap_device = args.next().ok_or("Missing tap device argument")?; let address_str = args.next().ok_or("Missing address argument")?; let port_str = args.next().ok_or("Missing port argument")?; let address: IpAddress = address_str.parse()?; let port: u16 = port_str.parse()?; Ok(ClientConfig { tap_device, address, port }) } } fn main() -> Result<(), String> { let config = ClientConfig::from_env()?; let mut device = TapInterface::new(&config.tap_device)?; device.set_hardware_address(wire::HardwareAddress::Ethernet(0x02.into()))?; let mut sockets = SocketSet::new(vec![]); let neighbor_cache = NeighborCache::new(Instant::now()); let routes = Routes::new(Instant::now()); let mut iface = InterfaceBuilder::new(&mut device) .hardware_addr(device.hardware_address().unwrap()) .ip_addr(Ipv4Address::new(192, 168, 69, 2).into()) .neighbor_cache(neighbor_cache) .routes(routes) .finalize()?; let tcp_rx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let tcp_tx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut tcp_socket = TCPv4::new(tcp_rx_buffer, tcp_tx_buffer)?; let tcp_handle = sockets.add(tcp_socket); let remote_endpoint = TCPv4Endpoint::new(config.address, config.port); loop { iface.poll(Instant::now(), &mut sockets)?; let mut socket = sockets.get_mut::(tcp_handle)?; if socket.state() == smoltcp::socket::tcp::State::Closed { socket.connect(iface.route_into(remote_endpoint.address), remote_endpoint, Instant::now())?; } if socket.can_recv() { let mut data = vec![0; 64]; let size = socket.recv(&mut data)?; if size > 0 { let mut reversed_data = data[..size].to_vec(); reversed_data.reverse(); socket.send(&reversed_data)?; } } } } ``` -------------------------------- ### Implement Throughput Benchmark Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md This example implements a simple throughput benchmark by establishing a connection to itself from a different thread. It measures data transfer rates for reading and writing. ```sh cargo run -q --release --example benchmark -- --tap tap0 reader ``` ```sh cargo run -q --release --example benchmark -- --tap tap0 writer ``` ```rust use std::env; use std::thread; use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes}; use smoltcp::phy::{Device, TapInterface}; use smoltcp::socket::{SocketSet, TCPv4, Socket, TCPv4Endpoint}; use smoltcp::time::{Duration, Instant}; use smoltcp::wire::{self, IpAddress, IpCidr, Ipv4Address}; const MTU: usize = 1500; enum BenchmarkMode { Reader, Writer, } struct BenchmarkConfig { tap_device: String, mode: BenchmarkMode, } impl BenchmarkConfig { fn from_env() -> Result { let mut args = env::args().skip(1); let tap_device = args.next().ok_or("Missing tap device argument")?; let mode_str = args.next().ok_or("Missing mode argument")?; let mode = match mode_str.as_str() { "reader" => BenchmarkMode::Reader, "writer" => BenchmarkMode::Writer, _ => return Err("Invalid mode argument. Use 'reader' or 'writer'.")?, }; Ok(BenchmarkConfig { tap_device, mode }) } } fn main() -> Result<(), String> { let config = BenchmarkConfig::from_env()?; let mut device = TapInterface::new(&config.tap_device)?; device.set_hardware_address(wire::HardwareAddress::Ethernet(0x02.into()))?; let mut sockets = SocketSet::new(vec![]); let neighbor_cache = NeighborCache::new(Instant::now()); let routes = Routes::new(Instant::now()); let mut iface = InterfaceBuilder::new(&mut device) .hardware_addr(device.hardware_address().unwrap()) .ip_addr(Ipv4Address::new(192, 168, 69, 1).into()) .neighbor_cache(neighbor_cache) .routes(routes) .finalize()?; let tcp_rx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let tcp_tx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut tcp_socket = TCPv4::new(tcp_rx_buffer, tcp_tx_buffer)?; let tcp_handle = sockets.add(tcp_socket); let remote_endpoint = TCPv4Endpoint::new(Ipv4Address::new(192, 168, 69, 1).into(), 1234.into()); let mut buffer = vec![0u8; MTU]; let mut total_bytes = 0; let start_time = Instant::now(); thread::spawn(move || { let mut sockets = SocketSet::new(vec![]); let neighbor_cache = NeighborCache::new(Instant::now()); let routes = Routes::new(Instant::now()); let mut device = TapInterface::new(&config.tap_device).unwrap(); device.set_hardware_address(wire::HardwareAddress::Ethernet(0x02.into())).unwrap(); let mut iface = InterfaceBuilder::new(&mut device) .hardware_addr(device.hardware_address().unwrap()) .ip_addr(Ipv4Address::new(192, 168, 69, 2).into()) .neighbor_cache(neighbor_cache) .routes(routes) .finalize() .unwrap(); let tcp_rx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let tcp_tx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut tcp_socket = TCPv4::new(tcp_rx_buffer, tcp_tx_buffer).unwrap(); let tcp_handle = sockets.add(tcp_socket); sockets.get_mut::(tcp_handle).unwrap().bind(1234.into()).unwrap(); loop { iface.poll(Instant::now(), &mut sockets).unwrap(); let mut socket = sockets.get_mut::(tcp_handle).unwrap(); if socket.state() == smoltcp::socket::tcp::State::Listen { socket.accept().unwrap(); } if socket.can_recv() { let mut buffer = vec![0u8; MTU]; let size = socket.recv(&mut buffer).unwrap(); if size > 0 { match config.mode { BenchmarkMode::Reader => { // Do nothing, just consume data } BenchmarkMode::Writer => { socket.send(&buffer[..size]).unwrap(); } } } } } }); loop { iface.poll(Instant::now(), &mut sockets)?; let mut socket = sockets.get_mut::(tcp_handle)?; if socket.state() == smoltcp::socket::tcp::State::Closed { socket.connect(iface.route_into(remote_endpoint.address), remote_endpoint, Instant::now())?; } match config.mode { BenchmarkMode::Reader => { if socket.can_send() { socket.send(&buffer)?; total_bytes += buffer.len(); } } BenchmarkMode::Writer => { if socket.can_recv() { let size = socket.recv(&mut buffer)?; if size > 0 { total_bytes += size; } } } } let elapsed = Instant::now() - start_time; if elapsed.total_millis() >= 1000.0 { let throughput_bps = (total_bytes as f64 * 8.0) / elapsed.total_millis() * 1000.0; println!("throughput: {:.3} Gbps", throughput_bps / 1e9); break; } } Ok(()) } ``` -------------------------------- ### Handling DHCPv4 ClientState in Rust Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/errors.md Example of checking the DHCPv4 client state to determine if a lease has been obtained or if a failure occurred, necessitating a reset. ```rust match socket.state() { ClientState::Bound => { println!("Got lease"); if let Some(config) = socket.config() { // Apply configuration } } ClientState::Idle => { // DHCP failed, may need to retry socket.reset(); } _ => { // In progress } } ``` -------------------------------- ### Markdown Table Documentation Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/INDEX.md Demonstrates the structure of Markdown tables used for documenting parameters, fields, and variants, including columns for Name, Type, Default, and Description. ```markdown | Column | Meaning | |--------|---------| | Name | Parameter, field, or variant name | | Type | Rust type (exact from source) | | Default | Default value if applicable | | Description | What it does or represents | ``` -------------------------------- ### Emulate Network Host with Basic Request Responses Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md This example emulates a network host responding to pings, UDP packets, and various TCP connections. It's useful for testing network interactions and resource exhaustion conditions. ```rust use std::env; use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes}; use smoltcp::phy::{Device, TapInterface}; use smoltcp::socket::{SocketSet, UDPv4, Socket, TCPv4, TCPv4Endpoint}; use smoltcp::time::{Duration, Instant}; use smoltcp::wire::{self, IpAddress, IpCidr, Ipv4Address}; const MTU: usize = 1500; struct ServerConfig { tap_device: String, } impl ServerConfig { fn from_env() -> Result { let mut args = env::args().skip(1); let tap_device = args.next().ok_or("Missing tap device argument")?; Ok(ServerConfig { tap_device }) } } fn main() -> Result<(), String> { let config = ServerConfig::from_env()?; let mut device = TapInterface::new(&config.tap_device)?; device.set_hardware_address(wire::HardwareAddress::Ethernet(0x02.into()))?; let mut sockets = SocketSet::new(vec![]); let neighbor_cache = NeighborCache::new(Instant::now()); let routes = Routes::new(Instant::now()); let mut iface = InterfaceBuilder::new(&mut device) .hardware_addr(device.hardware_address().unwrap()) .ip_addr(Ipv4Address::new(192, 168, 69, 1).into()) .neighbor_cache(neighbor_cache) .routes(routes) .finalize()?; // UDP server on port 6969 let udp_rx_buffer = smoltcp::socket::BytesStorage::new(vec![0; 64]); let udp_tx_buffer = smoltcp::socket::BytesStorage::new(vec![0; 64]); let mut udp_socket = UDPv4::new(udp_rx_buffer, udp_tx_buffer)?; let udp_handle = sockets.add(udp_socket); sockets.get_mut::(udp_handle)?.bind(6969.into())?; // TCP server on port 6969 let tcp_rx_buffer_6969 = smoltcp::socket::BytesStorage::new(vec![0; 64]); let tcp_tx_buffer_6969 = smoltcp::socket::BytesStorage::new(vec![0; 64]); let mut tcp_socket_6969 = TCPv4::new(tcp_rx_buffer_6969, tcp_tx_buffer_6969)?; let tcp_handle_6969 = sockets.add(tcp_socket_6969); sockets.get_mut::(tcp_handle_6969)?.bind(6969.into())?; // TCP server on port 6970 let tcp_rx_buffer_6970 = smoltcp::socket::BytesStorage::new(vec![0; 64]); let tcp_tx_buffer_6970 = smoltcp::socket::BytesStorage::new(vec![0; 64]); let mut tcp_socket_6970 = TCPv4::new(tcp_rx_buffer_6970, tcp_tx_buffer_6970)?; let tcp_handle_6970 = sockets.add(tcp_socket_6970); sockets.get_mut::(tcp_handle_6970)?.bind(6970.into())?; // TCP server on port 6971 let tcp_rx_buffer_6971 = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let tcp_tx_buffer_6971 = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut tcp_socket_6971 = TCPv4::new(tcp_rx_buffer_6971, tcp_tx_buffer_6971)?; let tcp_handle_6971 = sockets.add(tcp_socket_6971); sockets.get_mut::(tcp_handle_6971)?.bind(6971.into())?; sockets.get_mut::(tcp_handle_6971)?.set_keep_alive(Duration::from_secs(1))?; sockets.get_mut::(tcp_handle_6971)?.set_user_timeout(Duration::from_secs(2))?; // TCP server on port 6972 let tcp_rx_buffer_6972 = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let tcp_tx_buffer_6972 = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut tcp_socket_6972 = TCPv4::new(tcp_rx_buffer_6972, tcp_tx_buffer_6972)?; let tcp_handle_6972 = sockets.add(tcp_socket_6972); sockets.get_mut::(tcp_handle_6972)?.bind(6972.into())?; loop { iface.poll(Instant::now(), &mut sockets)?; // UDP server on port 6969 let mut socket = sockets.get_mut::(udp_handle)?; if let Some((data, remote_endpoint)) = socket.recvfrom()? { let mut reversed_data = data.to_vec(); reversed_data.reverse(); socket.sendto(reversed_data, remote_endpoint)?; } // TCP server on port 6969 let mut socket = sockets.get_mut::(tcp_handle_6969)?; if socket.can_recv() { socket.recv(|_| Ok(0))?; socket.send(b"hello")?; socket.close()?; } // TCP server on port 6970 let mut socket = sockets.get_mut::(tcp_handle_6970)?; if socket.can_recv() { let mut data = vec![0; 64]; let size = socket.recv(&mut data)?; if size > 0 { let mut reversed_data = data[..size].to_vec(); reversed_data.reverse(); socket.send(&reversed_data)?; } } // TCP server on port 6971 let mut socket = sockets.get_mut::(tcp_handle_6971)?; if socket.can_recv() { socket.recv(|_| Ok(0))?; } if socket.can_send() { socket.send(&[0])?; } // TCP server on port 6972 let mut socket = sockets.get_mut::(tcp_handle_6972)?; if socket.can_send() { socket.send(&[0])?; } } } ``` -------------------------------- ### Implement Ping Utility with Raw Sockets Source: https://github.com/smoltcp-rs/smoltcp/blob/main/README.md This example implements a minimal ping utility using raw sockets. It sends ICMP ECHO_REQUEST packets and processes ECHO_RESPONSE. The host is configured with specific hardware and IPv4 addresses. ```rust use std::env; use std::net::Ipv4Addr; use std::str::FromStr; use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes}; use smoltcp::phy::{Device, TapInterface}; use smoltcp::socket::{SocketSet, UDPv4, Socket, ICMPv4, ICMPv4Packet}; use smoltcp::time::{Duration, Instant}; use smoltcp::wire::{self, IpAddress, IpCidr, Ipv4Address}; const MTU: usize = 1500; struct PingConfig { host: Ipv4Address, interval: Duration, count: usize, } impl PingConfig { fn from_env() -> Result { let args: Vec = env::args().collect(); if args.len() < 2 { return Err("Missing host address argument".to_string()); } let host = Ipv4Address::from_str(&args[1]).map_err(|e| format!("{}", e))?; Ok(PingConfig { host, interval: Duration::from_secs(1), count: 4, }) } } fn main() -> Result<(), String> { let config = PingConfig::from_env()?; let mut args = env::args().skip(1); let _ = args.next(); // Skip host let tap_device = args.next().ok_or("Missing tap device argument")?; let mut device = TapInterface::new(&tap_device)?; device.set_hardware_address(wire::HardwareAddress::Ethernet(0x02.into()))?; let mut sockets = SocketSet::new(vec![]); let neighbor_cache = NeighborCache::new(Instant::now()); let routes = Routes::new(Instant::now()); let mut iface = InterfaceBuilder::new(&mut device) .hardware_addr(device.hardware_address().unwrap()) .ip_addr(Ipv4Address::new(192, 168, 69, 1).into()) .neighbor_cache(neighbor_cache) .routes(routes) .finalize()?; let icmp_rx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let icmp_tx_buffer = smoltcp::socket::BytesStorage::new(vec![0; MTU]); let mut icmp_socket = ICMPv4::new(icmp_rx_buffer, icmp_tx_buffer)?; let icmp_handle = sockets.add(icmp_socket); let mut packet_count = 0; let mut response_count = 0; let start_time = Instant::now(); loop { let elapsed = Instant::now() - start_time; if elapsed > config.interval * config.count as u32 { break; } if packet_count < config.count { let mut packet = ICMPv4Packet::new(vec![0; MTU]); packet.set_icmp_type(wire::ICMPv4Type::EchoRequest)?; packet.set_payload_len(0)?; packet.fill()?; let mut socket = sockets.get_mut::(icmp_handle)?; socket.send(packet.as_ref(), config.host.into())?; packet_count += 1; } iface.poll(Instant::now(), &mut sockets)?; let mut socket = sockets.get_mut::(icmp_handle)?; if let Some(packet) = socket.receive()? { if packet.icmp_type() == wire::ICMPv4Type::EchoReply { response_count += 1; println!("Received {} bytes from {}", packet.len(), config.host); } } } println!("{} packets transmitted, {} received", packet_count, response_count); Ok(()) } ``` -------------------------------- ### Configure IFACE_MAX_ADDR_COUNT via Environment Variable Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/configuration.md Set the maximum number of IP addresses per interface using an environment variable. This example sets it to 4 before building. ```bash SMOLTCP_IFACE_MAX_ADDR_COUNT=4 cargo build ``` -------------------------------- ### Start DNS Query Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md Initiates a DNS query for a specified hostname and query type. Use this when you need to resolve a hostname to an IP address. Ensure the hostname format is valid and that query slots are available. ```rust use smoltcp::wire::dns::Type; let handle = socket.start_query("example.com", Type::A, MulticastDns::Disabled)?; ``` -------------------------------- ### Rust Type Signature Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/INDEX.md Illustrates the notation used for Rust type signatures, including generic parameters, optional parameters, result types, and associated types. ```rust pub fn method(&mut self, param: Type) -> Result ``` -------------------------------- ### TxToken consume Method Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Shows how to use the consume method of TxToken to queue a frame for transmission. The closure receives a mutable buffer to write the frame data into, up to the specified length. ```rust tx_token.consume(64, |buf| { buf[0..4].copy_from_slice(b"DATA"); 4 }); ``` -------------------------------- ### Add IPv4 Routes to Interface Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/configuration.md Example of adding a default IPv4 route and a specific IPv4 route to an interface. Ensure the interface and necessary types are in scope. ```rust let routes = iface.routes(); routes.add_default_ipv4_route(Ipv4Address::new(192, 168, 1, 254))?; routes.add_ipv4_route( Ipv4Cidr::new(Ipv4Address::new(10, 0, 0, 0), 8), Ipv4Address::new(192, 168, 1, 253) )?; ``` -------------------------------- ### Create a new DHCPv4 Socket Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/dns-dhcpv4-socket.md Instantiates a new DHCP socket with default settings. This is the starting point for DHCPv4 client operations. ```rust use smoltcp::socket::dhcpv4::*; let socket = Socket::new(); ``` -------------------------------- ### Configure IFACE_MAX_ADDR_COUNT via Cargo Features Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/configuration.md Set the maximum number of IP addresses per interface using Cargo features. This example configures it to 4. ```toml [dependencies] smoltcp = { version = "0.13", features = ["iface-max-addr-count-4"] } ``` -------------------------------- ### wait Function Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Blocks until a device is ready or a deadline is reached. This is useful for polling network interfaces without busy-waiting. The `done` closure should check for interface activity. ```rust use smoltcp::phy::wait; wait(&mut device, deadline, || { iface.poll(Instant::now(), &mut device, &mut sockets) != PollResult::None }); ``` -------------------------------- ### RxToken consume Method Example Source: https://github.com/smoltcp-rs/smoltcp/blob/main/_autodocs/api-reference/device-phy.md Demonstrates how to use the consume method of RxToken to process received frame data. The closure provided to consume receives the frame data as a byte slice. ```rust let packet_len = rx_token.consume(|data| { println!("Frame: {:?}", data); data.len() }); ```