From 2e05a1bd0d79e9b1cc26911aba038a993920ea33 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 8 Jul 2022 17:58:13 +0800 Subject: [PATCH] Revert "Upgrade smoltcp 0.6.0 -> 0.8.0" This reverts commit c60de48a300a80c7ee9c3f09322510727f14d741. --- artiq/firmware/Cargo.lock | 14 +-- artiq/firmware/bootloader/Cargo.toml | 2 +- artiq/firmware/bootloader/main.rs | 23 +++-- artiq/firmware/libboard_misoc/Cargo.toml | 2 +- artiq/firmware/runtime/Cargo.toml | 2 +- artiq/firmware/runtime/main.rs | 53 +++++++---- artiq/firmware/runtime/sched.rs | 107 ++++++++++------------- 7 files changed, 97 insertions(+), 106 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 8e0c7f95a..e5d303a00 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -240,12 +240,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c75de51135344a4f8ed3cfe2720dc27736f7711989703a0b43aadf3753c55577" -[[package]] -name = "managed" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" - [[package]] name = "memchr" version = "2.4.1" @@ -327,7 +321,7 @@ dependencies = [ "io", "log", "logger_artiq", - "managed 0.7.2", + "managed", "proto_artiq", "riscv", "smoltcp", @@ -371,13 +365,13 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "smoltcp" -version = "0.8.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2308a1657c8db1f5b4993bab4e620bdbe5623bd81f254cf60326767bb243237" +checksum = "0fe46639fd2ec79eadf8fe719f237a7a0bd4dac5d957f1ca5bbdbc1c3c39e53a" dependencies = [ "bitflags", "byteorder", - "managed 0.8.0", + "managed", ] [[package]] diff --git a/artiq/firmware/bootloader/Cargo.toml b/artiq/firmware/bootloader/Cargo.toml index 9e5ba820a..5c2a54ba5 100644 --- a/artiq/firmware/bootloader/Cargo.toml +++ b/artiq/firmware/bootloader/Cargo.toml @@ -16,5 +16,5 @@ build_misoc = { path = "../libbuild_misoc" } byteorder = { version = "1.0", default-features = false } crc = { version = "1.7", default-features = false } board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp"] } -smoltcp = { version = "0.8.0", default-features = false, features = ["medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } +smoltcp = { version = "0.6.0", default-features = false, features = ["ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } riscv = { version = "0.6.0", features = ["inline-asm"] } diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index 535c6234d..555f8b0b6 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -18,8 +18,6 @@ use board_misoc::slave_fpga; use board_misoc::{clock, ethmac, net_settings}; use board_misoc::uart_console::Console; use riscv::register::{mcause, mepc, mtval}; -use smoltcp::iface::SocketStorage; -use smoltcp::wire::HardwareAddress; fn check_integrity() -> bool { extern { @@ -398,9 +396,6 @@ fn network_boot() { println!("Initializing network..."); - // Assuming only one socket is ever needed by the bootloader. - // The smoltcp reuses the listening socket when the connection is established. - let mut sockets = [SocketStorage::EMPTY]; let mut net_device = unsafe { ethmac::EthernetDevice::new() }; net_device.reset_phy_if_any(); @@ -417,15 +412,15 @@ fn network_boot() { let mut interface = match net_addresses.ipv6_addr { Some(addr) => { ip_addrs[2] = IpCidr::new(addr, 0); - smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..]) - .hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) + smoltcp::iface::EthernetInterfaceBuilder::new(net_device) + .ethernet_addr(net_addresses.hardware_addr) .ip_addrs(&mut ip_addrs[..]) .neighbor_cache(neighbor_cache) .finalize() } None => - smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..]) - .hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) + smoltcp::iface::EthernetInterfaceBuilder::new(net_device) + .ethernet_addr(net_addresses.hardware_addr) .ip_addrs(&mut ip_addrs[..2]) .neighbor_cache(neighbor_cache) .finalize() @@ -434,10 +429,14 @@ fn network_boot() { let mut rx_storage = [0; 4096]; let mut tx_storage = [0; 128]; + let mut socket_set_entries: [_; 1] = Default::default(); + let mut sockets = + smoltcp::socket::SocketSet::new(&mut socket_set_entries[..]); + let tcp_rx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut rx_storage[..]); let tcp_tx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut tx_storage[..]); let tcp_socket = smoltcp::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); - let tcp_handle = interface.add_socket(tcp_socket); + let tcp_handle = sockets.add(tcp_socket); let mut net_conn = NetConn::new(); let mut boot_time = None; @@ -447,7 +446,7 @@ fn network_boot() { loop { let timestamp = clock::get_ms() as i64; { - let socket = &mut *interface.get_socket::(tcp_handle); + let socket = &mut *sockets.get::(tcp_handle); match boot_time { None => { @@ -476,7 +475,7 @@ fn network_boot() { } } - match interface.poll(smoltcp::time::Instant::from_millis(timestamp)) { + match interface.poll(&mut sockets, smoltcp::time::Instant::from_millis(timestamp)) { Ok(_) => (), Err(smoltcp::Error::Unrecognized) => (), Err(err) => println!("Network error: {}", err) diff --git a/artiq/firmware/libboard_misoc/Cargo.toml b/artiq/firmware/libboard_misoc/Cargo.toml index 69c1d46d3..0d8d705cc 100644 --- a/artiq/firmware/libboard_misoc/Cargo.toml +++ b/artiq/firmware/libboard_misoc/Cargo.toml @@ -15,7 +15,7 @@ build_misoc = { path = "../libbuild_misoc" } [dependencies] byteorder = { version = "1.0", default-features = false } log = { version = "0.4", default-features = false, optional = true } -smoltcp = { version = "0.8.0", default-features = false, optional = true } +smoltcp = { version = "0.6.0", default-features = false, optional = true } riscv = { version = "0.6.0", features = ["inline-asm"] } [features] diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index 241246821..ee987ad2d 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -27,7 +27,7 @@ board_misoc = { path = "../libboard_misoc", features = ["uart_console", "smoltcp logger_artiq = { path = "../liblogger_artiq" } board_artiq = { path = "../libboard_artiq" } proto_artiq = { path = "../libproto_artiq", features = ["log", "alloc"] } -smoltcp = { version = "0.8.0", default-features = false, features = ["alloc", "medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } +smoltcp = { version = "0.6.0", default-features = false, features = ["alloc", "ethernet", "proto-ipv4", "proto-ipv6", "socket-tcp"] } riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index f8843352d..45fb76f91 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -27,7 +27,7 @@ extern crate riscv; use core::cell::RefCell; use core::convert::TryFrom; -use smoltcp::wire::{IpCidr, HardwareAddress}; +use smoltcp::wire::IpCidr; use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot}; #[cfg(has_ethmac)] @@ -123,33 +123,38 @@ fn startup() { net_device.reset_phy_if_any(); let net_device = { - use smoltcp::phy::Tracer; + use smoltcp::time::Instant; + use smoltcp::wire::PrettyPrinter; + use smoltcp::wire::EthernetFrame; - // We can't create the function pointer as a separate variable here because the type of - // the packet argument Packet isn't accessible and rust's type inference isn't sufficient - // to propagate in to a local var. - match config::read_str("net_trace", |r| r.map(|s| s == "1")) { - Ok(true) => Tracer::new(net_device, |timestamp, packet| { - print!("\x1b[37m[{:6}.{:03}s]\n{}\x1b[0m\n", - timestamp.secs(), timestamp.millis(), packet) - }), - _ => Tracer::new(net_device, |_, _| {}), + fn net_trace_writer(timestamp: Instant, printer: PrettyPrinter>) { + print!("\x1b[37m[{:6}.{:03}s]\n{}\x1b[0m\n", + timestamp.secs(), timestamp.millis(), printer) } + + fn net_trace_silent(_timestamp: Instant, _printer: PrettyPrinter>) {} + + let net_trace_fn: fn(Instant, PrettyPrinter>); + match config::read_str("net_trace", |r| r.map(|s| s == "1")) { + Ok(true) => net_trace_fn = net_trace_writer, + _ => net_trace_fn = net_trace_silent + } + smoltcp::phy::EthernetTracer::new(net_device, net_trace_fn) }; let neighbor_cache = smoltcp::iface::NeighborCache::new(alloc::collections::btree_map::BTreeMap::new()); let net_addresses = net_settings::get_adresses(); info!("network addresses: {}", net_addresses); - let interface = match net_addresses.ipv6_addr { + let mut interface = match net_addresses.ipv6_addr { Some(addr) => { let ip_addrs = [ IpCidr::new(net_addresses.ipv4_addr, 0), IpCidr::new(net_addresses.ipv6_ll_addr, 0), IpCidr::new(addr, 0) ]; - smoltcp::iface::InterfaceBuilder::new(net_device, vec![]) - .hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) + smoltcp::iface::EthernetInterfaceBuilder::new(net_device) + .ethernet_addr(net_addresses.hardware_addr) .ip_addrs(ip_addrs) .neighbor_cache(neighbor_cache) .finalize() @@ -159,8 +164,8 @@ fn startup() { IpCidr::new(net_addresses.ipv4_addr, 0), IpCidr::new(net_addresses.ipv6_ll_addr, 0) ]; - smoltcp::iface::InterfaceBuilder::new(net_device, vec![]) - .hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr)) + smoltcp::iface::EthernetInterfaceBuilder::new(net_device) + .ethernet_addr(net_addresses.hardware_addr) .ip_addrs(ip_addrs) .neighbor_cache(neighbor_cache) .finalize() @@ -179,7 +184,7 @@ fn startup() { drtio_routing::interconnect_disable_all(); let aux_mutex = sched::Mutex::new(); - let mut scheduler = sched::Scheduler::new(interface); + let mut scheduler = sched::Scheduler::new(); let io = scheduler.io(); rtio_mgt::startup(&io, &aux_mutex, &drtio_routing_table, &up_destinations); @@ -206,7 +211,19 @@ fn startup() { let mut net_stats = ethmac::EthernetStatistics::new(); loop { scheduler.run(); - scheduler.run_network(); + + { + let sockets = &mut *scheduler.sockets().borrow_mut(); + loop { + let timestamp = smoltcp::time::Instant::from_millis(clock::get_ms() as i64); + match interface.poll(sockets, timestamp) { + Ok(true) => (), + Ok(false) => break, + Err(smoltcp::Error::Unrecognized) => (), + Err(err) => debug!("network error: {}", err) + } + } + } if let Some(_net_stats_diff) = net_stats.update() { debug!("ethernet mac:{}", ethmac::EthernetStatistics::new()); diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index 991569cd1..d6a347269 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -9,13 +9,11 @@ use fringe::generator::{Generator, Yielder, State as GeneratorState}; use smoltcp::time::Duration; use smoltcp::Error as NetworkError; use smoltcp::wire::IpEndpoint; -use smoltcp::iface::{Interface, SocketHandle}; +use smoltcp::socket::{SocketHandle, SocketRef}; use io::{Read, Write}; use board_misoc::clock; use urc::Urc; -use board_misoc::ethmac::EthernetDevice; -use smoltcp::phy::Tracer; #[derive(Fail, Debug)] pub enum Error { @@ -33,6 +31,8 @@ impl From for Error { } } +type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>; + #[derive(Debug)] struct WaitRequest { event: Option<*mut dyn FnMut() -> bool>, @@ -59,7 +59,7 @@ impl Thread { unsafe fn new(io: &Io, stack_size: usize, f: F) -> ThreadHandle where F: 'static + FnOnce(Io) + Send { let spawned = io.spawned.clone(); - let network = io.network.clone(); + let sockets = io.sockets.clone(); // Add a 4k stack guard to the stack of any new threads let stack = OwnedStack::new(stack_size + 4096); @@ -67,8 +67,8 @@ impl Thread { generator: Generator::unsafe_new(stack, |yielder, _| { f(Io { yielder: Some(yielder), - spawned, - network + spawned: spawned, + sockets: sockets }) }), waiting_for: WaitRequest { @@ -115,21 +115,19 @@ impl ThreadHandle { } } -type Network = Interface<'static, Tracer>; - pub struct Scheduler { threads: Vec, spawned: Urc>>, - network: Urc>, + sockets: Urc>, run_idx: usize, } impl Scheduler { - pub fn new(network: Network) -> Scheduler { + pub fn new() -> Scheduler { Scheduler { threads: Vec::new(), spawned: Urc::new(RefCell::new(Vec::new())), - network: Urc::new(RefCell::new(network)), + sockets: Urc::new(RefCell::new(SocketSet::new(Vec::new()))), run_idx: 0, } } @@ -138,11 +136,13 @@ impl Scheduler { Io { yielder: None, spawned: self.spawned.clone(), - network: self.network.clone() + sockets: self.sockets.clone() } } pub fn run(&mut self) { + self.sockets.borrow_mut().prune(); + self.threads.append(&mut *self.spawned.borrow_mut()); if self.threads.len() == 0 { return } @@ -188,17 +188,8 @@ impl Scheduler { } } - pub fn run_network(&mut self) { - let mut interface = self.network.borrow_mut(); - loop { - let timestamp = smoltcp::time::Instant::from_millis(clock::get_ms() as i64); - match interface.poll(timestamp) { - Ok(true) => (), - Ok(false) => break, - Err(smoltcp::Error::Unrecognized) => (), - Err(err) => debug!("network error: {}", err) - } - } + pub fn sockets(&self) -> &RefCell { + &*self.sockets } } @@ -206,7 +197,7 @@ impl Scheduler { pub struct Io<'a> { yielder: Option<&'a Yielder>, spawned: Urc>>, - network: Urc>, + sockets: Urc>, } impl<'a> Io<'a> { @@ -300,10 +291,10 @@ impl<'a> Drop for MutexGuard<'a> { macro_rules! until { ($socket:expr, $ty:ty, |$var:ident| $cond:expr) => ({ - let (network, handle) = ($socket.io.network.clone(), $socket.handle); + let (sockets, handle) = ($socket.io.sockets.clone(), $socket.handle); $socket.io.until(move || { - let mut network = network.borrow_mut(); - let $var = network.get_socket::<$ty>(handle); + let mut sockets = sockets.borrow_mut(); + let $var = sockets.get::<$ty>(handle); $cond }) }) @@ -325,9 +316,9 @@ impl<'a> TcpListener<'a> { fn new_lower(io: &'a Io<'a>, buffer_size: usize) -> SocketHandle { let rx_buffer = vec![0; buffer_size]; let tx_buffer = vec![0; buffer_size]; - io.network + io.sockets .borrow_mut() - .add_socket(TcpSocketLower::new( + .add(TcpSocketLower::new( TcpSocketBuffer::new(rx_buffer), TcpSocketBuffer::new(tx_buffer))) } @@ -342,9 +333,9 @@ impl<'a> TcpListener<'a> { } fn with_lower(&self, f: F) -> R - where F: FnOnce(&mut TcpSocketLower) -> R { - let mut network = self.io.network.borrow_mut(); - let result = f(network.get_socket(self.handle.get())); + where F: FnOnce(SocketRef) -> R { + let mut sockets = self.io.sockets.borrow_mut(); + let result = f(sockets.get(self.handle.get())); result } @@ -362,7 +353,7 @@ impl<'a> TcpListener<'a> { pub fn listen>(&self, endpoint: T) -> Result<(), Error> { let endpoint = endpoint.into(); - self.with_lower(|s| s.listen(endpoint)) + self.with_lower(|mut s| s.listen(endpoint)) .map(|()| { self.endpoint.set(endpoint); () @@ -374,10 +365,10 @@ impl<'a> TcpListener<'a> { // We're waiting until at least one half of the connection becomes open. // This handles the case where a remote socket immediately sends a FIN-- // that still counts as accepting even though nothing may be sent. - let (network, handle) = (self.io.network.clone(), self.handle.get()); + let (sockets, handle) = (self.io.sockets.clone(), self.handle.get()); self.io.until(move || { - let mut network = network.borrow_mut(); - let socket = network.get_socket::(handle); + let mut sockets = sockets.borrow_mut(); + let socket = sockets.get::(handle); socket.may_send() || socket.may_recv() })?; @@ -394,14 +385,14 @@ impl<'a> TcpListener<'a> { } pub fn close(&self) { - self.with_lower(|s| s.close()) + self.with_lower(|mut s| s.close()) } } impl<'a> Drop for TcpListener<'a> { fn drop(&mut self) { - self.with_lower(|s| s.close()); - self.io.network.borrow_mut().remove_socket(self.handle.get()); + self.with_lower(|mut s| s.close()); + self.io.sockets.borrow_mut().release(self.handle.get()) } } @@ -425,9 +416,9 @@ impl<'a> TcpStream<'a> { } fn with_lower(&self, f: F) -> R - where F: FnOnce(&mut TcpSocketLower) -> R { - let mut network = self.io.network.borrow_mut(); - let result = f(network.get_socket(self.handle)); + where F: FnOnce(SocketRef) -> R { + let mut sockets = self.io.sockets.borrow_mut(); + let result = f(sockets.get(self.handle)); result } @@ -464,7 +455,7 @@ impl<'a> TcpStream<'a> { } pub fn set_timeout(&self, value: Option) { - self.with_lower(|s| s.set_timeout(value.map(Duration::from_millis))) + self.with_lower(|mut s| s.set_timeout(value.map(Duration::from_millis))) } pub fn keep_alive(&self) -> Option { @@ -472,11 +463,11 @@ impl<'a> TcpStream<'a> { } pub fn set_keep_alive(&self, value: Option) { - self.with_lower(|s| s.set_keep_alive(value.map(Duration::from_millis))) + self.with_lower(|mut s| s.set_keep_alive(value.map(Duration::from_millis))) } pub fn close(&self) -> Result<(), Error> { - self.with_lower(|s| s.close()); + self.with_lower(|mut s| s.close()); until!(self, TcpSocketLower, |s| !s.is_open())?; // right now the socket may be in TIME-WAIT state. if we don't give it a chance to send // a packet, and the user code executes a loop { s.listen(); s.read(); s.close(); } @@ -490,33 +481,23 @@ impl<'a> Read for TcpStream<'a> { fn read(&mut self, buf: &mut [u8]) -> Result { // Only borrow the underlying socket for the span of the next statement. - let result = self.with_lower(|s| s.recv_slice(buf)); + let result = self.with_lower(|mut s| s.recv_slice(buf)); match result { // Slow path: we need to block until buffer is non-empty. Ok(0) => { until!(self, TcpSocketLower, |s| s.can_recv() || !s.may_recv())?; - match self.with_lower(|s| s.recv_slice(buf)) { + match self.with_lower(|mut s| s.recv_slice(buf)) { Ok(length) => Ok(length), - Err(NetworkError::Finished) | Err(NetworkError::Illegal) => Ok(0), - Err(e) => { - panic!("Unexpected error from smoltcp: {}", e); - } + _ => unreachable!() } } // Fast path: we had data in buffer. Ok(length) => Ok(length), - // We've received a fin. - Err(NetworkError::Finished) | // Error path: the receive half of the socket is not open. Err(NetworkError::Illegal) => Ok(0), // No other error may be returned. - Err(e) => { - // This could return Err(Error::Network(e)) rather than panic, - // but I expect that'll just cause a panic later perhaps with - // less interesting context. - panic!("Unexpected error from smoltcp: {}", e); - } + Err(_) => unreachable!() } } } @@ -527,12 +508,12 @@ impl<'a> Write for TcpStream<'a> { fn write(&mut self, buf: &[u8]) -> Result { // Only borrow the underlying socket for the span of the next statement. - let result = self.with_lower(|s| s.send_slice(buf)); + let result = self.with_lower(|mut s| s.send_slice(buf)); match result { // Slow path: we need to block until buffer is non-full. Ok(0) => { until!(self, TcpSocketLower, |s| s.can_send() || !s.may_send())?; - match self.with_lower(|s| s.send_slice(buf)) { + match self.with_lower(|mut s| s.send_slice(buf)) { Ok(length) => Ok(length), Err(NetworkError::Illegal) => Ok(0), _ => unreachable!() @@ -559,7 +540,7 @@ impl<'a> Write for TcpStream<'a> { impl<'a> Drop for TcpStream<'a> { fn drop(&mut self) { - self.with_lower(|s| s.close()); - self.io.network.borrow_mut().remove_socket(self.handle); + self.with_lower(|mut s| s.close()); + self.io.sockets.borrow_mut().release(self.handle) } }