diff --git a/examples/benchmark.rs b/examples/benchmark.rs index 626a2db..4ccff15 100644 --- a/examples/benchmark.rs +++ b/examples/benchmark.rs @@ -11,7 +11,6 @@ mod utils; use std::cmp; use std::collections::BTreeMap; use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT}; -use std::time::Instant; use std::thread; use std::io::{Read, Write}; use std::net::TcpStream; @@ -21,6 +20,7 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::SocketSet; use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; +use smoltcp::time::{Duration, Instant}; const AMOUNT: usize = 1_000_000_000; @@ -52,9 +52,7 @@ fn client(kind: Client) { let end = Instant::now(); - let elapsed = end - start; - let elapsed = elapsed.as_secs() as f64 - + elapsed.subsec_nanos() as f64 * 1e-9; + let elapsed = (end - start).total_millis() as f64 / 1000.0; println!("throughput: {:.3} Gbps", AMOUNT as f64 / elapsed / 0.125e9); @@ -84,8 +82,6 @@ fn main() { thread::spawn(move || client(mode)); - let startup_time = Instant::now(); - let neighbor_cache = NeighborCache::new(BTreeMap::new()); let tcp1_rx_buffer = TcpSocketBuffer::new(vec![0; 65535]); @@ -107,10 +103,11 @@ fn main() { let mut sockets = SocketSet::new(vec![]); let tcp1_handle = sockets.add(tcp1_socket); let tcp2_handle = sockets.add(tcp2_socket); + let default_timeout = Some(Duration::from_millis(1000)); let mut processed = 0; while !CLIENT_DONE.load(Ordering::SeqCst) { - let timestamp = utils::millis_since(startup_time); + let timestamp = Instant::now(); iface.poll(&mut sockets, timestamp).expect("poll error"); // tcp:1234: emit data @@ -149,6 +146,14 @@ fn main() { } } - phy_wait(fd, iface.poll_delay(&sockets, timestamp).or(Some(1000))).expect("wait error"); + match iface.poll_at(&sockets, timestamp) { + Some(poll_at) if timestamp < poll_at => { + phy_wait(fd, Some(poll_at - timestamp)).expect("wait error"); + }, + Some(_) => (), + None => { + phy_wait(fd, default_timeout).expect("wait error"); + } + } } } diff --git a/examples/client.rs b/examples/client.rs index 31d7cdc..0d84efe 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -8,12 +8,12 @@ mod utils; use std::str::{self, FromStr}; use std::collections::BTreeMap; -use std::time::Instant; use std::os::unix::io::AsRawFd; use smoltcp::phy::wait as phy_wait; use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; +use smoltcp::time::Instant; fn main() { utils::setup_logging(""); @@ -31,8 +31,6 @@ fn main() { let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); let port = u16::from_str(&matches.free[1]).expect("invalid port format"); - let startup_time = Instant::now(); - let neighbor_cache = NeighborCache::new(BTreeMap::new()); let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 64]); @@ -59,7 +57,7 @@ fn main() { let mut tcp_active = false; loop { - let timestamp = utils::millis_since(startup_time); + let timestamp = Instant::now(); iface.poll(&mut sockets, timestamp).expect("poll error"); { diff --git a/examples/httpclient.rs b/examples/httpclient.rs index 436f96d..7f31bee 100644 --- a/examples/httpclient.rs +++ b/examples/httpclient.rs @@ -10,13 +10,13 @@ mod utils; use std::str::{self, FromStr}; use std::collections::BTreeMap; -use std::time::Instant; use std::os::unix::io::AsRawFd; use url::Url; use smoltcp::phy::wait as phy_wait; use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; +use smoltcp::time::Instant; fn main() { utils::setup_logging(""); @@ -34,7 +34,6 @@ fn main() { let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format"); let url = Url::parse(&matches.free[1]).expect("invalid url format"); - let startup_time = Instant::now(); let neighbor_cache = NeighborCache::new(BTreeMap::new()); @@ -59,7 +58,7 @@ fn main() { let mut state = State::Connect; loop { - let timestamp = utils::millis_since(startup_time); + let timestamp = Instant::now(); iface.poll(&mut sockets, timestamp).expect("poll error"); { diff --git a/examples/loopback.rs b/examples/loopback.rs index 496d8fb..8a0c859 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -20,24 +20,26 @@ use smoltcp::phy::Loopback; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer}; +use smoltcp::time::{Duration, Instant}; #[cfg(not(feature = "std"))] mod mock { + use smoltcp::time::{Duration, Instant}; use core::cell::Cell; #[derive(Debug)] - pub struct Clock(Cell); + pub struct Clock(Cell); impl Clock { pub fn new() -> Clock { - Clock(Cell::new(0)) + Clock(Cell::new(Instant::from_millis(0))) } - pub fn advance(&self, millis: u64) { - self.0.set(self.0.get() + millis) + pub fn advance(&self, duration: Duration) { + self.0.set(self.0.get() + duration) } - pub fn elapsed(&self) -> u64 { + pub fn elapsed(&self) -> Instant { self.0.get() } } @@ -47,6 +49,7 @@ mod mock { mod mock { use std::sync::Arc; use std::sync::atomic::{Ordering, AtomicUsize}; + use smoltcp::time::{Duration, Instant}; // should be AtomicU64 but that's unstable #[derive(Debug, Clone)] @@ -57,12 +60,12 @@ mod mock { Clock(Arc::new(AtomicUsize::new(0))) } - pub fn advance(&self, millis: u64) { - self.0.fetch_add(millis as usize, Ordering::SeqCst); + pub fn advance(&self, duration: Duration) { + self.0.fetch_add(duration.total_millis() as usize, Ordering::SeqCst); } - pub fn elapsed(&self) -> u64 { - self.0.load(Ordering::SeqCst) as u64 + pub fn elapsed(&self) -> Instant { + Instant::from_millis(self.0.load(Ordering::SeqCst) as i64) } } } @@ -123,7 +126,7 @@ fn main() { let mut did_listen = false; let mut did_connect = false; let mut done = false; - while !done && clock.elapsed() < 10_000 { + while !done && clock.elapsed() < Instant::from_millis(10_000) { iface.poll(&mut socket_set, clock.elapsed()).expect("poll error"); { @@ -164,13 +167,12 @@ fn main() { } match iface.poll_delay(&socket_set, clock.elapsed()) { - Some(0) => - debug!("resuming"), + Some(Duration { millis: 0 }) => debug!("resuming"), Some(delay) => { debug!("sleeping for {} ms", delay); clock.advance(delay) - } - None => clock.advance(1) + }, + None => clock.advance(Duration::from_millis(1)) } } diff --git a/examples/ping.rs b/examples/ping.rs index 15ab2a9..b95ad99 100644 --- a/examples/ping.rs +++ b/examples/ping.rs @@ -9,8 +9,9 @@ mod utils; use std::str::FromStr; use std::collections::BTreeMap; -use std::time::Instant; +use std::cmp; use std::os::unix::io::AsRawFd; +use smoltcp::time::{Duration, Instant}; use smoltcp::phy::Device; use smoltcp::phy::wait as phy_wait; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, @@ -41,10 +42,12 @@ fn main() { let device_caps = device.capabilities(); let address = Ipv4Address::from_str(&matches.free[0]).expect("invalid address format"); let count = matches.opt_str("count").map(|s| usize::from_str(&s).unwrap()).unwrap_or(4); - let interval = matches.opt_str("interval").map(|s| u64::from_str(&s).unwrap()).unwrap_or(1); - let timeout = matches.opt_str("timeout").map(|s| u64::from_str(&s).unwrap()).unwrap_or(5); - - let startup_time = Instant::now(); + let interval = matches.opt_str("interval") + .map(|s| Duration::from_secs(u64::from_str(&s).unwrap())) + .unwrap_or(Duration::from_secs(1)); + let timeout = Duration::from_secs( + matches.opt_str("timeout").map(|s| u64::from_str(&s).unwrap()).unwrap_or(5) + ); let neighbor_cache = NeighborCache::new(BTreeMap::new()); @@ -68,7 +71,7 @@ fn main() { let mut sockets = SocketSet::new(vec![]); let icmp_handle = sockets.add(icmp_socket); - let mut send_at = 0; + let mut send_at = Instant::from_millis(0); let mut seq_no = 0; let mut received = 0; let mut echo_payload = [0xffu8; 40]; @@ -77,22 +80,19 @@ fn main() { let endpoint = IpAddress::Ipv4(remote_addr); loop { - let timestamp = utils::millis_since(startup_time); - iface.poll(&mut sockets, timestamp).expect("poll error"); + iface.poll(&mut sockets, Instant::now()).unwrap(); { + let timestamp = Instant::now(); let mut socket = sockets.get::(icmp_handle); if !socket.is_open() { - socket.bind(IcmpEndpoint::Ident(ident)).unwrap() + socket.bind(IcmpEndpoint::Ident(ident)).unwrap(); + send_at = timestamp; } - let timestamp = Instant::now().duration_since(startup_time); - let timestamp_us = (timestamp.as_secs() * 1000000) + - (timestamp.subsec_nanos() / 1000) as u64; - if socket.can_send() && seq_no < count as u16 && - send_at <= utils::millis_since(startup_time) { - NetworkEndian::write_u64(&mut echo_payload, timestamp_us); + send_at <= timestamp { + NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis()); let icmp_repr = Icmpv4Repr::EchoRequest { ident: ident, seq_no, @@ -108,7 +108,7 @@ fn main() { waiting_queue.insert(seq_no, timestamp); seq_no += 1; - send_at += interval * 1000; + send_at += interval; } if socket.can_recv() { @@ -118,10 +118,10 @@ fn main() { if let Icmpv4Repr::EchoReply { seq_no, data, .. } = icmp_repr { if let Some(_) = waiting_queue.get(&seq_no) { - let packet_timestamp_us = NetworkEndian::read_u64(data); + let packet_timestamp_us = NetworkEndian::read_i64(data); println!("{} bytes from {}: icmp_seq={}, time={:.3}ms", data.len(), remote_addr, seq_no, - (timestamp_us - packet_timestamp_us) as f64 / 1000.0); + (timestamp.total_millis() - packet_timestamp_us) as f64 / 1000.0); waiting_queue.remove(&seq_no); received += 1; } @@ -129,7 +129,7 @@ fn main() { } waiting_queue.retain(|seq, from| { - if (timestamp - *from).as_secs() < timeout { + if timestamp - *from < timeout { true } else { println!("From {} icmp_seq={} timeout", remote_addr, seq); @@ -142,11 +142,17 @@ fn main() { } } - let timestamp = utils::millis_since(startup_time); - - let poll_at = iface.poll_at(&sockets, timestamp); - let resume_at = [poll_at, Some(send_at)].iter().flat_map(|x| *x).min(); - phy_wait(fd, resume_at.map(|at| at.saturating_sub(timestamp))).expect("wait error"); + let timestamp = Instant::now(); + match iface.poll_at(&sockets, timestamp) { + Some(poll_at) if timestamp < poll_at => { + let resume_at = cmp::min(poll_at, send_at); + phy_wait(fd, Some(resume_at - timestamp)).expect("wait error"); + }, + Some(_) => (), + None => { + phy_wait(fd, Some(send_at - timestamp)).expect("wait error"); + } + } } println!("--- {} ping statistics ---", remote_addr); diff --git a/examples/server.rs b/examples/server.rs index 2d22a9d..9ca77cd 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -9,7 +9,6 @@ mod utils; use std::str; use std::collections::BTreeMap; use std::fmt::Write; -use std::time::Instant; use std::os::unix::io::AsRawFd; use smoltcp::phy::wait as phy_wait; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; @@ -17,6 +16,7 @@ use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder}; use smoltcp::socket::SocketSet; use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketBuffer}; use smoltcp::socket::{TcpSocket, TcpSocketBuffer}; +use smoltcp::time::Instant; fn main() { utils::setup_logging(""); @@ -30,8 +30,6 @@ fn main() { let fd = device.as_raw_fd(); let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false); - let startup_time = Instant::now(); - let neighbor_cache = NeighborCache::new(BTreeMap::new()); let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketBuffer::new(vec![0; 64])]); @@ -71,7 +69,7 @@ fn main() { let mut tcp_6970_active = false; loop { - let timestamp = utils::millis_since(startup_time); + let timestamp = Instant::now(); iface.poll(&mut sockets, timestamp).expect("poll error"); // udp:6969: respond "hello" diff --git a/examples/utils.rs b/examples/utils.rs index ef7a5c3..f976a7c 100644 --- a/examples/utils.rs +++ b/examples/utils.rs @@ -5,7 +5,7 @@ use std::str::{self, FromStr}; use std::rc::Rc; use std::io; use std::fs::File; -use std::time::{Instant, SystemTime, UNIX_EPOCH}; +use std::time::{SystemTime, UNIX_EPOCH}; use std::env; use std::process; #[cfg(feature = "log")] @@ -18,14 +18,15 @@ use smoltcp::phy::{Device, EthernetTracer, FaultInjector}; #[cfg(feature = "phy-tap_interface")] use smoltcp::phy::TapInterface; use smoltcp::phy::{PcapWriter, PcapSink, PcapMode, PcapLinkType}; +use smoltcp::time::Instant; #[cfg(feature = "log")] pub fn setup_logging_with_clock(filter: &str, since_startup: F) - where F: Fn() -> u64 + Send + Sync + 'static { + where F: Fn() -> Instant + Send + Sync + 'static { LogBuilder::new() .format(move |record: &LogRecord| { let elapsed = since_startup(); - let timestamp = format!("[{:6}.{:03}s]", elapsed / 1000, elapsed % 1000); + let timestamp = format!("[{}]", elapsed); if record.target().starts_with("smoltcp::") { format!("\x1b[0m{} ({}): {}\x1b[0m", timestamp, record.target().replace("smoltcp::", ""), record.args()) @@ -47,10 +48,8 @@ pub fn setup_logging_with_clock(filter: &str, since_startup: F) #[cfg(feature = "log")] pub fn setup_logging(filter: &str) { - let startup_at = Instant::now(); setup_logging_with_clock(filter, move || { - let elapsed = Instant::now().duration_since(startup_at); - elapsed.as_secs() * 1000 + (elapsed.subsec_nanos() / 1000000) as u64 + Instant::now() }) } @@ -142,10 +141,3 @@ pub fn parse_middleware_options(matches: &mut Matches, device: D, loopback: b device.set_bucket_interval(shaping_interval); device } - -pub fn millis_since(startup_time: Instant) -> u64 { - let duration = Instant::now().duration_since(startup_time); - let duration_ms = (duration.as_secs() * 1000) + - (duration.subsec_nanos() / 1000000) as u64; - duration_ms -}