Browse Source

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

whitequark 8 years ago
parent
commit
7381e7f98b

+ 4 - 2
src/iface/ethernet.rs

@@ -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()) {

+ 6 - 6
src/phy/fault_injector.rs

@@ -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> {

+ 37 - 7
src/phy/mod.rs

@@ -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.
     ///

+ 7 - 2
src/phy/raw_socket.rs

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

+ 7 - 2
src/phy/tap_interface.rs

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

+ 2 - 2
src/phy/tracer.rs

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

+ 3 - 2
src/socket/mod.rs

@@ -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))
     }
 }
 

+ 9 - 4
src/socket/tcp.rs

@@ -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);

+ 2 - 1
src/socket/udp.rs

@@ -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));