From 89b7c9e09112bea921f76f8e9c028b63218e0862 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 25 Oct 2017 02:31:27 +0000 Subject: [PATCH] Update smoltcp. Fixes #840. --- artiq/firmware/Cargo.lock | 6 +- artiq/firmware/runtime/Cargo.toml | 4 +- artiq/firmware/runtime/ethmac.rs | 12 +-- artiq/firmware/runtime/lib.rs | 18 ++-- artiq/firmware/runtime/sched.rs | 148 ++++++++++++++++-------------- 5 files changed, 101 insertions(+), 87 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index dfddf22e7..4be1bd427 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -158,7 +158,7 @@ dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "logger_artiq 0.0.0", "proto 0.0.0", - "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=6f5ae33)", + "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=f64a99a)", "std_artiq 0.0.0", ] @@ -184,7 +184,7 @@ dependencies = [ [[package]] name = "smoltcp" version = "0.4.0" -source = "git+https://github.com/m-labs/smoltcp?rev=6f5ae33#6f5ae33501827d57926469c6f1a860205a24f7ae" +source = "git+https://github.com/m-labs/smoltcp?rev=f64a99a#f64a99a4e6d744c3a6f3d9a54a0fb3f94e4b0ec8" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -222,7 +222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log_buffer 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec57723b84bbe7bdf76aa93169c9b59e67473317c6de3a83cb2a0f8ccb2aa493" "checksum managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d48e8c30a4363e2981fe4db20527f6ab0f32a243bbc75379dea5a64f60dae4" "checksum rustc-cfg 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704" -"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=6f5ae33)" = "" +"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp?rev=f64a99a)" = "" "checksum walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd7c16466ecc507c7cb5988db03e6eab4aaeab89a5c37a29251fcfd3ac9b7afe" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index 5013d9878..f2eaec653 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -37,6 +37,6 @@ features = ["alloc"] [dependencies.smoltcp] git = "https://github.com/m-labs/smoltcp" -rev = "6f5ae33" +rev = "f64a99a" default-features = false -features = ["alloc", "log"] +features = ["alloc", "log", "proto-udp", "proto-tcp"] diff --git a/artiq/firmware/runtime/ethmac.rs b/artiq/firmware/runtime/ethmac.rs index 68db8cbde..638bfda2e 100644 --- a/artiq/firmware/runtime/ethmac.rs +++ b/artiq/firmware/runtime/ethmac.rs @@ -1,7 +1,7 @@ use core::slice; use board::{csr, mem}; use smoltcp::Error; -use smoltcp::phy::{DeviceLimits, Device}; +use smoltcp::phy::{DeviceCapabilities, Device}; const RX0_BASE: usize = mem::ETHMAC_BASE + 0x0000; const RX1_BASE: usize = mem::ETHMAC_BASE + 0x0800; @@ -23,11 +23,11 @@ impl Device for EthernetDevice { type RxBuffer = RxBuffer; type TxBuffer = TxBuffer; - fn limits(&self) -> DeviceLimits { - let mut limits = DeviceLimits::default(); - limits.max_transmission_unit = 1514; - limits.max_burst_size = Some(RX_BUFFERS.len()); - limits + fn capabilities(&self) -> DeviceCapabilities { + let mut caps = DeviceCapabilities::default(); + caps.max_transmission_unit = 1514; + caps.max_burst_size = Some(RX_BUFFERS.len()); + caps } fn receive(&mut self, _timestamp: u64) -> Result { diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index c9b9acb1f..9849b3661 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -22,7 +22,7 @@ extern crate amp; extern crate drtioaux; use std::boxed::Box; -use smoltcp::wire::{EthernetAddress, IpAddress}; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use proto::{mgmt_proto, analyzer_proto, moninj_proto, rpc_proto, session_proto, kernel_proto}; use amp::{mailbox, rpc_queue}; @@ -93,15 +93,15 @@ fn startup() { } } - let protocol_addr; + let protocol_cidr; match config::read_str("ip", |r| r?.parse()) { - Err(()) | Ok(IpAddress::Unspecified) => { - protocol_addr = IpAddress::v4(192, 168, 1, 50); - info!("using default IP address {}", protocol_addr); + Err(()) => { + protocol_cidr = IpCidr::new(IpAddress::v4(192, 168, 1, 50), 24); + info!("using default IP address {}", protocol_cidr); } - Ok(addr) => { - protocol_addr = addr; - info!("using IP address {}", protocol_addr); + Ok(cidr) => { + protocol_cidr = cidr; + info!("using IP address {}", protocol_cidr); } } @@ -117,7 +117,7 @@ fn startup() { let arp_cache = smoltcp::iface::SliceArpCache::new([Default::default(); 8]); let mut interface = smoltcp::iface::EthernetInterface::new( Box::new(net_device), Box::new(arp_cache) as Box, - hardware_addr, [protocol_addr]); + hardware_addr, [protocol_cidr], None); let mut scheduler = sched::Scheduler::new(); let io = scheduler.io(); diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index b69f87da4..4b4be6f9e 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -1,19 +1,20 @@ #![allow(dead_code)] use std::mem; -use std::cell::{Cell, RefCell, RefMut}; +use std::cell::{Cell, RefCell}; use std::vec::Vec; use std::io::{Read, Write, Result, Error, ErrorKind}; use fringe::OwnedStack; use fringe::generator::{Generator, Yielder, State as GeneratorState}; use smoltcp::wire::IpEndpoint; -use smoltcp::socket::{AsSocket, SocketHandle}; -type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>; +use smoltcp::socket::{SocketHandle, SocketRef}; use board; use urc::Urc; +type SocketSet = ::smoltcp::socket::SocketSet<'static, 'static, 'static>; + #[derive(Debug)] struct WaitRequest { event: Option<*const (Fn() -> bool + 'static)>, @@ -241,12 +242,13 @@ macro_rules! until { let (sockets, handle) = ($socket.io.sockets.clone(), $socket.handle); $socket.io.until(move || { let mut sockets = borrow_mut!(sockets); - let $var: &mut $ty = sockets.get_mut(handle).as_socket(); + let $var = sockets.get::<$ty>(handle); $cond }) }) } + use ::smoltcp::Error as ErrorLower; // https://github.com/rust-lang/rust/issues/44057 // type ErrorLower = ::smoltcp::Error; @@ -278,40 +280,44 @@ impl<'a> UdpSocket<'a> { } } - fn as_lower<'b>(&'b self) -> RefMut<'b, UdpSocketLower> { - RefMut::map(borrow_mut!(self.io.sockets), - |sockets| sockets.get_mut(self.handle).as_socket()) + fn with_lower(&self, f: F) -> R + where F: FnOnce(SocketRef) -> R { + let mut sockets = borrow_mut!(self.io.sockets); + let result = f(sockets.get(self.handle)); + result } pub fn bind>(&self, endpoint: T) -> Result<()> { - match self.as_lower().bind(endpoint) { - Ok(()) => Ok(()), - Err(ErrorLower::Illegal) => - Err(Error::new(ErrorKind::Other, "already listening")), - Err(ErrorLower::Unaddressable) => - Err(Error::new(ErrorKind::AddrNotAvailable, "port cannot be zero")), - _ => unreachable!() - } + self.with_lower(|mut s| s.bind(endpoint)) + .map_err(|err| { + match err { + ErrorLower::Illegal => + Error::new(ErrorKind::Other, "already listening"), + ErrorLower::Unaddressable => + Error::new(ErrorKind::AddrNotAvailable, "port cannot be zero"), + _ => unreachable!() + } + }) } pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint)> { until!(self, UdpSocketLower, |s| s.can_recv())?; - match self.as_lower().recv_slice(buf) { - Ok(result) => Ok(result), - Err(_) => unreachable!() - } + self.with_lower(|mut s| s.recv_slice(buf)) + .map_err(|_| unreachable!()) } pub fn send_to(&self, buf: &[u8], addr: IpEndpoint) -> Result<()> { until!(self, UdpSocketLower, |s| s.can_send())?; - match self.as_lower().send_slice(buf, addr) { - Ok(()) => Ok(()), - Err(ErrorLower::Unaddressable) => - Err(Error::new(ErrorKind::AddrNotAvailable, "unaddressable destination")), - Err(ErrorLower::Truncated) => - Err(Error::new(ErrorKind::Other, "packet does not fit in buffer")), - Err(_) => unreachable!() - } + self.with_lower(|mut s| s.send_slice(buf, addr)) + .map_err(|err| { + match err { + ErrorLower::Unaddressable => + Error::new(ErrorKind::AddrNotAvailable, "unaddressable destination"), + ErrorLower::Truncated => + Error::new(ErrorKind::Other, "packet does not fit in buffer"), + _ => unreachable!() + } + }) } } @@ -352,35 +358,41 @@ impl<'a> TcpListener<'a> { } } - fn as_lower<'b>(&'b self) -> RefMut<'b, TcpSocketLower> { - RefMut::map(borrow_mut!(self.io.sockets), - |sockets| sockets.get_mut(self.handle.get()).as_socket()) + fn with_lower(&self, f: F) -> R + where F: FnOnce(SocketRef) -> R { + let mut sockets = borrow_mut!(self.io.sockets); + let result = f(sockets.get(self.handle.get())); + result } pub fn is_open(&self) -> bool { - self.as_lower().is_open() + self.with_lower(|s| s.is_open()) } pub fn can_accept(&self) -> bool { - self.as_lower().is_active() + self.with_lower(|s| s.is_active()) } pub fn local_endpoint(&self) -> IpEndpoint { - self.as_lower().local_endpoint() + self.with_lower(|s| s.local_endpoint()) } pub fn listen>(&self, endpoint: T) -> Result<()> { let endpoint = endpoint.into(); - match self.as_lower().listen(endpoint) { - Ok(()) => Ok(()), - Err(ErrorLower::Illegal) => - Err(Error::new(ErrorKind::Other, "already listening")), - Err(ErrorLower::Unaddressable) => - Err(Error::new(ErrorKind::InvalidInput, "port cannot be zero")), - _ => unreachable!() - }?; - self.endpoint.set(endpoint); - Ok(()) + self.with_lower(|mut s| s.listen(endpoint)) + .map(|()| { + self.endpoint.set(endpoint); + () + }) + .map_err(|err| { + match err { + ErrorLower::Illegal => + Error::new(ErrorKind::Other, "already listening"), + ErrorLower::Unaddressable => + Error::new(ErrorKind::InvalidInput, "port cannot be zero"), + _ => unreachable!() + } + }) } pub fn accept(&self) -> Result> { @@ -390,7 +402,7 @@ impl<'a> TcpListener<'a> { let (sockets, handle) = (self.io.sockets.clone(), self.handle.get()); self.io.until(move || { let mut sockets = borrow_mut!(sockets); - let socket: &mut TcpSocketLower = sockets.get_mut(handle).as_socket(); + let socket = sockets.get::(handle); socket.may_send() || socket.may_recv() })?; @@ -407,13 +419,13 @@ impl<'a> TcpListener<'a> { } pub fn close(&self) { - self.as_lower().close() + self.with_lower(|mut s| s.close()) } } impl<'a> Drop for TcpListener<'a> { fn drop(&mut self) { - self.as_lower().close(); + self.with_lower(|mut s| s.close()); borrow_mut!(self.io.sockets).release(self.handle.get()) } } @@ -437,57 +449,59 @@ impl<'a> TcpStream<'a> { } } - fn as_lower<'b>(&'b self) -> RefMut<'b, TcpSocketLower> { - RefMut::map(borrow_mut!(self.io.sockets), - |sockets| sockets.get_mut(self.handle).as_socket()) + fn with_lower(&self, f: F) -> R + where F: FnOnce(SocketRef) -> R { + let mut sockets = borrow_mut!(self.io.sockets); + let result = f(sockets.get(self.handle)); + result } pub fn is_open(&self) -> bool { - self.as_lower().is_open() + self.with_lower(|s| s.is_open()) } pub fn may_send(&self) -> bool { - self.as_lower().may_send() + self.with_lower(|s| s.may_send()) } pub fn may_recv(&self) -> bool { - self.as_lower().may_recv() + self.with_lower(|s| s.may_recv()) } pub fn can_send(&self) -> bool { - self.as_lower().can_send() + self.with_lower(|s| s.can_send()) } pub fn can_recv(&self) -> bool { - self.as_lower().can_recv() + self.with_lower(|s| s.can_recv()) } pub fn local_endpoint(&self) -> IpEndpoint { - self.as_lower().local_endpoint() + self.with_lower(|s| s.local_endpoint()) } pub fn remote_endpoint(&self) -> IpEndpoint { - self.as_lower().remote_endpoint() + self.with_lower(|s| s.remote_endpoint()) } pub fn timeout(&self) -> Option { - self.as_lower().timeout() + self.with_lower(|s| s.timeout()) } pub fn set_timeout(&self, value: Option) { - self.as_lower().set_timeout(value) + self.with_lower(|mut s| s.set_timeout(value)) } pub fn keep_alive(&self) -> Option { - self.as_lower().keep_alive() + self.with_lower(|s| s.keep_alive()) } pub fn set_keep_alive(&self, value: Option) { - self.as_lower().set_keep_alive(value) + self.with_lower(|mut s| s.set_keep_alive(value)) } pub fn close(&self) -> Result<()> { - self.as_lower().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(); } @@ -499,12 +513,12 @@ impl<'a> TcpStream<'a> { 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.as_lower().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.as_lower().recv_slice(buf) { + match self.with_lower(|mut s| s.recv_slice(buf)) { Ok(length) => Ok(length), Err(ErrorLower::Illegal) => Ok(0), _ => unreachable!() @@ -523,12 +537,12 @@ impl<'a> Read for TcpStream<'a> { 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.as_lower().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.as_lower().send_slice(buf) { + match self.with_lower(|mut s| s.send_slice(buf)) { Ok(length) => Ok(length), Err(ErrorLower::Illegal) => Ok(0), _ => unreachable!() @@ -545,7 +559,7 @@ impl<'a> Write for TcpStream<'a> { fn flush(&mut self) -> Result<()> { until!(self, TcpSocketLower, |s| s.send_queue() == 0 || !s.may_send())?; - if self.as_lower().send_queue() == 0 { + if self.with_lower(|s| s.send_queue()) == 0 { Ok(()) } else { Err(Error::new(ErrorKind::ConnectionAborted, "connection aborted")) @@ -555,7 +569,7 @@ impl<'a> Write for TcpStream<'a> { impl<'a> Drop for TcpStream<'a> { fn drop(&mut self) { - self.as_lower().close(); + self.with_lower(|mut s| s.close()); borrow_mut!(self.io.sockets).release(self.handle) } }