fn Device::mtu() -> usize → Device::limits() -> DeviceLimits

This commit is contained in:
whitequark 2017-03-07 10:56:48 +00:00
parent 6ad8872e15
commit 1d46ccf432
9 changed files with 77 additions and 28 deletions

View File

@ -367,11 +367,13 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let src_protocol_addrs = self.protocol_addrs.as_ref();
let arp_cache = &mut self.arp_cache;
let device = &mut self.device;
let mtu = device.mtu() - EthernetFrame::<&[u8]>::header_len();
let mut limits = device.limits();
limits.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len();
let mut nothing_to_transmit = true;
for socket in sockets.iter_mut() {
let result = socket.dispatch(timestamp, mtu, &mut |repr, payload| {
let result = socket.dispatch(timestamp, &limits, &mut |repr, payload| {
let repr = try!(repr.lower(src_protocol_addrs));
match arp_cache.lookup(&repr.dst_addr()) {

View File

@ -1,5 +1,5 @@
use Error;
use super::Device;
use super::{DeviceLimits, Device};
// We use our own RNG to stay compatible with #![no_std].
// The use of the RNG below has a slight bias, but it doesn't matter.
@ -98,12 +98,12 @@ impl<T: Device> Device for FaultInjector<T>
type RxBuffer = T::RxBuffer;
type TxBuffer = TxBuffer<T::TxBuffer>;
fn mtu(&self) -> usize {
if self.lower.mtu() < MTU {
self.lower.mtu()
} else {
MTU
fn limits(&self) -> DeviceLimits {
let mut limits = self.lower.limits();
if limits.max_transmission_unit > MTU {
limits.max_transmission_unit = MTU;
}
limits
}
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {

View File

@ -18,7 +18,7 @@
```rust
use std::slice;
use smoltcp::Error;
use smoltcp::phy::Device;
use smoltcp::phy::{DeviceLimits, Device};
const TX_BUFFERS: [*mut u8; 2] = [0x10000000 as *mut u8, 0x10001000 as *mut u8];
const RX_BUFFERS: [*mut u8; 2] = [0x10002000 as *mut u8, 0x10003000 as *mut u8];
@ -50,7 +50,12 @@ impl Device for EthernetDevice {
type RxBuffer = &'static [u8];
type TxBuffer = EthernetTxBuffer;
fn mtu(&self) -> usize { 1536 }
fn limits(&self) -> DeviceLimits {
let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1536;
limits.max_burst_size = Some(2);
limits
}
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
if rx_full() {
@ -114,6 +119,34 @@ pub use self::raw_socket::RawSocket;
#[cfg(all(feature = "std", target_os = "linux"))]
pub use self::tap_interface::TapInterface;
/// A description of device limitations.
///
/// Higher-level protocols may achieve higher throughput or lower latency if they consider
/// the bandwidth or packet size limitations.
#[derive(Debug, Clone, Default)]
pub struct DeviceLimits {
/// Maximum transmission unit.
///
/// The network device is unable to send or receive frames larger than the value returned
/// by this function.
///
/// For Ethernet, MTU will fall between 576 (for IPv4) or 1280 (for IPv6) and 9216 octets.
pub max_transmission_unit: usize,
/// Maximum burst size, in terms of MTU.
///
/// The network device is unable to send or receive bursts large than the value returned
/// by this function.
///
/// If `None`, there is no fixed limit on burst size, e.g. if network buffers are
/// dynamically allocated.
pub max_burst_size: Option<usize>,
/// Only present to prevent people from trying to initialize every field of DeviceLimits,
/// which would not let us add new fields in the future.
dummy: ()
}
/// An interface for sending and receiving raw network frames.
///
/// It is expected that a `Device` implementation would allocate memory for both sending
@ -123,11 +156,8 @@ pub trait Device {
type RxBuffer: AsRef<[u8]>;
type TxBuffer: AsRef<[u8]> + AsMut<[u8]>;
/// Get maximum transmission unit.
///
/// The network device is unable to send or receive frames larger than the MTU.
/// In practice, MTU will fall between 576 (for IPv4) or 1280 (for IPv6) and 9216 octets.
fn mtu(&self) -> usize;
/// Get a description of device limitations.
fn limits(&self) -> DeviceLimits;
/// Receive a frame.
///

View File

@ -4,7 +4,7 @@ use std::rc::Rc;
use std::io;
use Error;
use super::{sys, Device};
use super::{sys, DeviceLimits, Device};
/// A socket that captures or transmits the complete frame.
#[derive(Debug)]
@ -33,7 +33,12 @@ impl Device for RawSocket {
type RxBuffer = Vec<u8>;
type TxBuffer = TxBuffer;
fn mtu(&self) -> usize { self.mtu }
fn limits(&self) -> DeviceLimits {
DeviceLimits {
max_transmission_unit: self.mtu,
..DeviceLimits::default()
}
}
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
let mut lower = self.lower.borrow_mut();

View File

@ -4,7 +4,7 @@ use std::rc::Rc;
use std::io;
use Error;
use super::{sys, Device};
use super::{sys, DeviceLimits, Device};
/// A virtual Ethernet interface.
#[derive(Debug)]
@ -33,7 +33,12 @@ impl Device for TapInterface {
type RxBuffer = Vec<u8>;
type TxBuffer = TxBuffer;
fn mtu(&self) -> usize { self.mtu }
fn limits(&self) -> DeviceLimits {
DeviceLimits {
max_transmission_unit: self.mtu,
..DeviceLimits::default()
}
}
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
let mut lower = self.lower.borrow_mut();

View File

@ -1,6 +1,6 @@
use Error;
use wire::pretty_print::{PrettyPrint, PrettyPrinter};
use super::Device;
use super::{DeviceLimits, Device};
/// A tracer device.
///
@ -43,7 +43,7 @@ impl<T: Device, U: PrettyPrint> Device for Tracer<T, U> {
type RxBuffer = T::RxBuffer;
type TxBuffer = TxBuffer<T::TxBuffer, U>;
fn mtu(&self) -> usize { self.lower.mtu() }
fn limits(&self) -> DeviceLimits { self.lower.limits() }
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
let buffer = try!(self.lower.receive());

View File

@ -11,6 +11,7 @@
//! size for a buffer, allocate it, and let the networking stack use it.
use Error;
use phy::DeviceLimits;
use wire::IpRepr;
mod udp;
@ -92,10 +93,10 @@ impl<'a, 'b> Socket<'a, 'b> {
/// is returned.
///
/// This function is used internally by the networking stack.
pub fn dispatch<F, R>(&mut self, timestamp: u64, mtu: usize,
pub fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, mtu, emit))
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, limits, emit))
}
}

View File

@ -2,6 +2,7 @@ use core::fmt;
use managed::Managed;
use Error;
use phy::DeviceLimits;
use wire::{IpProtocol, IpAddress, IpEndpoint};
use wire::{TcpSeqNumber, TcpPacket, TcpRepr, TcpControl};
use socket::{Socket, IpRepr, IpPayload};
@ -916,7 +917,7 @@ impl<'a> TcpSocket<'a> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch<F, R>(&mut self, timestamp: u64, mtu: usize,
pub fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
if self.remote_endpoint.is_unspecified() { return Err(Error::Exhausted) }
@ -1080,8 +1081,10 @@ impl<'a> TcpSocket<'a> {
let ip_repr = try!(ip_repr.lower(&[]));
if repr.control == TcpControl::Syn {
let mtu = mtu - header_len - ip_repr.buffer_len();
repr.max_seg_size = Some(mtu as u16);
let mut max_segment_size = limits.max_transmission_unit;
max_segment_size -= header_len;
max_segment_size -= ip_repr.buffer_len();
repr.max_seg_size = Some(max_segment_size as u16);
}
emit(&ip_repr, &repr)
@ -1196,7 +1199,9 @@ mod test {
fn recv<F>(socket: &mut TcpSocket, timestamp: u64, mut f: F)
where F: FnMut(Result<TcpRepr, Error>) {
let mut buffer = vec![];
let result = socket.dispatch(timestamp, 1520, &mut |ip_repr, payload| {
let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1520;
let result = socket.dispatch(timestamp, &limits, &mut |ip_repr, payload| {
assert_eq!(ip_repr.protocol(), IpProtocol::Tcp);
assert_eq!(ip_repr.src_addr(), LOCAL_IP);
assert_eq!(ip_repr.dst_addr(), REMOTE_IP);

View File

@ -1,6 +1,7 @@
use managed::Managed;
use Error;
use phy::DeviceLimits;
use wire::{IpProtocol, IpEndpoint};
use wire::{UdpPacket, UdpRepr};
use socket::{Socket, IpRepr, IpPayload};
@ -232,7 +233,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
}
/// See [Socket::dispatch](enum.Socket.html#method.dispatch).
pub fn dispatch<F, R>(&mut self, _timestamp: u64, _mtu: usize,
pub fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
emit: &mut F) -> Result<R, Error>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R, Error> {
let packet_buf = try!(self.tx_buffer.dequeue().map_err(|()| Error::Exhausted));