Update iface and phy_wait to use new time types
Update the EthernetInterface poll functions to use Instant and Duration instead of a simple u64 value. Closes: #141 Approved by: whitequarkv0.7.x
parent
8b0ab0dc94
commit
1f9e14de71
|
@ -5,6 +5,7 @@ use core::cmp;
|
|||
use managed::ManagedSlice;
|
||||
|
||||
use {Error, Result};
|
||||
use time::{Duration, Instant};
|
||||
use phy::{Device, DeviceCapabilities, RxToken, TxToken};
|
||||
use wire::pretty_print::PrettyPrinter;
|
||||
use wire::{EthernetAddress, EthernetProtocol, EthernetFrame};
|
||||
|
@ -300,9 +301,6 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
/// Transmit packets queued in the given sockets, and receive packets queued
|
||||
/// in the device.
|
||||
///
|
||||
/// The timestamp must be a number of milliseconds, monotonically increasing
|
||||
/// since an arbitrary moment in time, such as system startup.
|
||||
///
|
||||
/// This function returns a boolean value indicating whether any packets were
|
||||
/// processed or emitted, and thus, whether the readiness of any socket might
|
||||
/// have changed.
|
||||
|
@ -317,7 +315,7 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
/// packets containing any unsupported protocol, option, or form, which is
|
||||
/// a very common occurrence and on a production system it should not even
|
||||
/// be logged.
|
||||
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
|
||||
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: Instant) -> Result<bool> {
|
||||
let mut readiness_may_have_changed = false;
|
||||
loop {
|
||||
let processed_any = self.socket_ingress(sockets, timestamp)?;
|
||||
|
@ -332,38 +330,42 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
}
|
||||
|
||||
/// Return a _soft deadline_ for calling [poll] the next time.
|
||||
/// That is, if `iface.poll_at(&sockets, 1000)` returns `Ok(Some(2000))`,
|
||||
/// you should call call [poll] in 1000 ms; it is harmless (but wastes energy)
|
||||
/// to call it 500 ms later, and potentially harmful (impacting quality of service)
|
||||
/// to call it 1500 ms later.
|
||||
///
|
||||
/// The timestamp argument is the same as for [poll].
|
||||
/// The [Instant] returned is the time at which you should call [poll] next.
|
||||
/// It is harmless (but wastes energy) to call it before the [Instant], and
|
||||
/// potentially harmful (impacting quality of service) to call it after the
|
||||
/// [Instant]
|
||||
///
|
||||
/// [poll]: #method.poll
|
||||
pub fn poll_at(&self, sockets: &SocketSet, timestamp: u64) -> Option<u64> {
|
||||
/// [Instant]: struct.Instant.html
|
||||
pub fn poll_at(&self, sockets: &SocketSet, timestamp: Instant) -> Option<Instant> {
|
||||
sockets.iter().filter_map(|socket| {
|
||||
let socket_poll_at = socket.poll_at();
|
||||
socket.meta().poll_at(socket_poll_at, |ip_addr|
|
||||
self.inner.has_neighbor(&ip_addr, timestamp))
|
||||
}).min()
|
||||
self.inner.has_neighbor(&ip_addr, timestamp.total_millis() as u64))
|
||||
}).min().map(|x| Instant::from_millis(x as i64))
|
||||
}
|
||||
|
||||
/// Return an _advisory wait time_ for calling [poll] the next time.
|
||||
/// That is, if `iface.poll_at(&sockets, 1000)` returns `Ok(Some(1000))`,
|
||||
/// you should call call [poll] in 1000 ms; it is harmless (but wastes energy)
|
||||
/// to call it 500 ms later, and potentially harmful (impacting quality of service)
|
||||
/// to call it 1500 ms later.
|
||||
///
|
||||
/// This is a shortcut for `poll_at(..., timestamp).map(|at| at.saturating_sub(timestamp))`.
|
||||
///
|
||||
/// The timestamp argument is the same as for [poll].
|
||||
/// The [Duration] returned is the time left to wait before calling [poll] next.
|
||||
/// It is harmless (but wastes energy) to call it before the [Duration] has passed,
|
||||
/// and potentially harmful (impacting quality of service) to call it after the
|
||||
/// [Duration] has passed.
|
||||
///
|
||||
/// [poll]: #method.poll
|
||||
pub fn poll_delay(&self, sockets: &SocketSet, timestamp: u64) -> Option<u64> {
|
||||
self.poll_at(sockets, timestamp).map(|at| at.saturating_sub(timestamp))
|
||||
/// [Duration]: struct.Duration.html
|
||||
pub fn poll_delay(&self, sockets: &SocketSet, timestamp: Instant) -> Option<Duration> {
|
||||
match self.poll_at(sockets, timestamp) {
|
||||
Some(poll_at) if timestamp < poll_at => {
|
||||
Some(poll_at - timestamp)
|
||||
}
|
||||
Some(_) => {
|
||||
Some(Duration::from_millis(0))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn socket_ingress(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
|
||||
fn socket_ingress(&mut self, sockets: &mut SocketSet, timestamp: Instant) -> Result<bool> {
|
||||
let mut processed_any = false;
|
||||
loop {
|
||||
let &mut Self { ref mut device, ref mut inner } = self;
|
||||
|
@ -371,15 +373,15 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
None => break,
|
||||
Some(tokens) => tokens,
|
||||
};
|
||||
rx_token.consume(timestamp, |frame| {
|
||||
inner.process_ethernet(sockets, timestamp, &frame).map_err(|err| {
|
||||
rx_token.consume(timestamp.total_millis() as u64, |frame| {
|
||||
inner.process_ethernet(sockets, timestamp.total_millis() as u64, &frame).map_err(|err| {
|
||||
net_debug!("cannot process ingress packet: {}", err);
|
||||
net_debug!("packet dump follows:\n{}",
|
||||
PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &frame));
|
||||
err
|
||||
}).and_then(|response| {
|
||||
processed_any = true;
|
||||
inner.dispatch(tx_token, timestamp, response).map_err(|err| {
|
||||
inner.dispatch(tx_token, timestamp.total_millis() as u64, response).map_err(|err| {
|
||||
net_debug!("cannot dispatch response packet: {}", err);
|
||||
err
|
||||
})
|
||||
|
@ -389,14 +391,14 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
Ok(processed_any)
|
||||
}
|
||||
|
||||
fn socket_egress(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
|
||||
fn socket_egress(&mut self, sockets: &mut SocketSet, timestamp: Instant) -> Result<bool> {
|
||||
let mut caps = self.device.capabilities();
|
||||
caps.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len();
|
||||
|
||||
let mut emitted_any = false;
|
||||
for mut socket in sockets.iter_mut() {
|
||||
if !socket.meta_mut().egress_permitted(|ip_addr|
|
||||
self.inner.has_neighbor(&ip_addr, timestamp)) {
|
||||
self.inner.has_neighbor(&ip_addr, timestamp.total_millis() as u64)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -409,7 +411,7 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
let response = $response;
|
||||
neighbor_addr = response.neighbor_addr();
|
||||
let tx_token = device.transmit().ok_or(Error::Exhausted)?;
|
||||
device_result = inner.dispatch(tx_token, timestamp, response);
|
||||
device_result = inner.dispatch(tx_token, timestamp.total_millis() as u64, response);
|
||||
device_result
|
||||
})
|
||||
}
|
||||
|
@ -436,7 +438,7 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
respond!(Packet::Udp(response))),
|
||||
#[cfg(feature = "socket-tcp")]
|
||||
Socket::Tcp(ref mut socket) =>
|
||||
socket.dispatch(timestamp, &caps, |response|
|
||||
socket.dispatch(timestamp.total_millis() as u64, &caps, |response|
|
||||
respond!(Packet::Tcp(response))),
|
||||
Socket::__Nonexhaustive(_) => unreachable!()
|
||||
};
|
||||
|
@ -449,7 +451,7 @@ impl<'b, 'c, DeviceT> Interface<'b, 'c, DeviceT>
|
|||
// requests from the socket. However, without an additional rate limiting
|
||||
// mechanism, we would spin on every socket that has yet to discover its
|
||||
// neighboor.
|
||||
socket.meta_mut().neighbor_missing(timestamp,
|
||||
socket.meta_mut().neighbor_missing(timestamp.total_millis() as u64,
|
||||
neighbor_addr.expect("non-IP response packet"));
|
||||
break
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use libc;
|
||||
use std::{mem, ptr, io};
|
||||
use std::os::unix::io::RawFd;
|
||||
use time::Duration;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[path = "linux.rs"]
|
||||
|
@ -19,7 +20,7 @@ pub use self::raw_socket::RawSocketDesc;
|
|||
pub use self::tap_interface::TapInterfaceDesc;
|
||||
|
||||
/// Wait until given file descriptor becomes readable, but no longer than given timeout.
|
||||
pub fn wait(fd: RawFd, millis: Option<u64>) -> io::Result<()> {
|
||||
pub fn wait(fd: RawFd, duration: Option<Duration>) -> io::Result<()> {
|
||||
unsafe {
|
||||
let mut readfds = mem::uninitialized::<libc::fd_set>();
|
||||
libc::FD_ZERO(&mut readfds);
|
||||
|
@ -33,8 +34,8 @@ pub fn wait(fd: RawFd, millis: Option<u64>) -> io::Result<()> {
|
|||
|
||||
let mut timeout = libc::timeval { tv_sec: 0, tv_usec: 0 };
|
||||
let timeout_ptr =
|
||||
if let Some(millis) = millis {
|
||||
timeout.tv_usec = (millis * 1_000) as libc::suseconds_t;
|
||||
if let Some(duration) = duration {
|
||||
timeout.tv_usec = (duration.total_millis() * 1_000) as libc::suseconds_t;
|
||||
&mut timeout as *mut _
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
|
|
Loading…
Reference in New Issue