|
@@ -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::<IcmpSocket>(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);
|